我在接受采访时被问到两个线程如何同时访问同步块,但我无法想出可能发生的情况。两个线程是否可以同时访问同步块?
答案 0 :(得分:4)
同步块的原因是为了防止两个线程同时访问该块。这当然只有在两个线程在同一个对象上同步时才会成立。例如,如果你这样做:
synchronized (new Object()) {
// Multiple threads can execute here at the same time.
}
然后可以在同一个块中同时执行多个线程。
答案 1 :(得分:2)
同步块的全部目的是防止您要求的内容,因此您必须删除同步块。
答案 2 :(得分:1)
使用semaphores 可以。请看下面的代码:
// 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();
}
信号量只允许2个线程进入同步块。
答案 3 :(得分:0)
两个线程不能同时访问同步块。
同步的主要目标是以防止多个线程对同一方法/块进行并发访问。
来自Java docs Synchronization
线程主要通过共享对字段的访问和参考字段引用的对象进行通信。这种通信形式非常有效,但可能会出现两种错误:线程干扰和内存一致性错误。防止这些错误所需的工具是同步。
synchronized(object){
//block of statements to be synchronized
}
这里,object是对正在同步的对象的引用。
同步块确保只有在当前线程成功进入对象监视器后,才会调用对象成员的方法。
一些相关链接
答案 4 :(得分:0)
如果进入同步块的线程看到相同的锁定,则定义了块,则这是不可能的。
然而,如果问题一般是关于“同步块”,而没有提到被获取的锁定对象,那么这是允许的。例如:
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);
}
};
....
}
}
在这个例子中,由于线程t1在s1上操作而线程t2在s2上操作,因此没有什么能阻止线程同时在同步块内。线程使用不同的锁。互斥是由锁实例决定的,而不是由仅定义范围的synchronized块决定的。