两个线程如何同时访问同步块

时间:2013-11-11 07:20:20

标签: java multithreading

我在接受采访时被问到两个线程如何同时访问同步块,但我无法想出可能发生的情况。两个线程是否可以同时访问同步块?

5 个答案:

答案 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是对正在同步的对象的引用。

  

同步块确保只有在当前线程成功进入对象监视器后,才会调用对象成员的方法。

一些相关链接

  1. javatpoint.com synchronization
  2. tutorialspoint.com java_thread_synchronization

答案 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块决定的。