在面试中,我被问到两个线程如何同时访问同步块的问题,但我无法想出可能发生这种情况的场景。两个线程是否可以同时访问同步块?
在面试中,我被问到两个线程如何同时访问同步块的问题,但我无法想出可能发生这种情况的场景。两个线程是否可以同时访问同步块?
synchronized (new Object()) {
// Multiple threads can execute here at the same time.
}
多个线程就可以在同一块中同时执行。
// Create a semaphore with 2 permitted threads
private static Semaphore semaphore = new Semaphore(2);
public static void main(String[] args) {
// Create 10 threads which will call the critical section
for (int i = 0; i < 10; i++) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
criticalSection();
} catch (InterruptedException ignored) {
}
}
};
Thread t = new Thread(runnable);
t.setName("Thread No. " + i);
t.start();
}
}
private static void criticalSection() throws InterruptedException {
// Try to enter the critical section (synchronized block)
semaphore.acquire();
System.out.println("Some heavy job. Thread ID = " + Thread.currentThread().getName());
Thread.sleep(3000);
semaphore.release();
}
两个线程不能同时访问同步块。
同步的主要目的是防止多个线程并发访问相同的方法/块。
来自Java文档同步。
线程主要通过共享对字段和对象引用字段所引用的访问来通信。这种形式的通信非常高效,但可能会出现两种错误:线程干扰和内存一致性错误。防止这些错误所需的工具是同步。
synchronized(object){
//block of statements to be synchronized
}
在这里,对象是指正在同步的对象的引用。
同步块确保在当前线程成功进入对象的监视器后才调用对象成员的方法。
一些相关链接
如果进入同步块的线程看到的是相同的锁,那么这是不可能的。
然而,如果问题涉及到一般的“同步块”,而没有提到获取的锁对象,则是允许的。例如:
public class MyStats {
private long total;
private int count;
public void add(long value) {
synchronized(this) {
this.total += value;
this.count++;
}
}
public static void main(String[] args) {
final MyStats s1 = new MyStats();
final MyStats s2 = new MyStats();
Thread t1 = new Thread() {
public void run() {
s1.add(100);
}
};
Thread t2 = new Thread() {
public void run() {
s2.add(200);
}
};
....
}
}