4

我在一次采访中被问到两个线程如何同时访问同步块,但我无法想出它可能发生的场景。两个线程可以同时访问一个同步块吗?

4

5 回答 5

4

使用同步块的原因是为了防止两个线程同时访问该块。这当然只有当两个线程在同一个对象上同步时才成立。例如,如果您执行以下操作:

synchronized (new Object()) {
// Multiple threads can execute here at the same time.
}

然后多个线程可以同时在同一个块中执行。

于 2013-11-11T07:22:31.513 回答
2

同步块的全部目的是防止你问什么,所以你必须删除同步块。

于 2013-11-11T07:23:18.350 回答
1

可以使用信号量来实现。看下面的代码:

// 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 个线程进入同步块。

于 2013-11-11T09:28:07.077 回答
0

两个线程不能同时访问一个同步块。

同步的主要目标是防止多个线程同时访问同一方法/块。

来自 Java 文档同步

线程主要通过共享对字段和对象引用字段的访问来进行通信。这种通信形式非常高效,但会导致两种错误:线程干扰和内存一致性错误。防止这些错误所需的工具是同步。

synchronized(object){
  //block of statements to be synchronized
}

这里,object 是对正在同步的对象的引用。

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

一些相关链接

  1. javatpoint.com 同步
  2. tutorialspoint.com java_thread_synchronization
于 2013-11-11T07:49:59.080 回答
0

If the threads entering the synchronized block see the same lock the block is defined on, then this is impossible.

However, if the question is regarding a "synchronized block" in general, without mentioning to the lock object/s being acquired, then this is allowed. For example:

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);
      }
    };
    ....
  }
}

In this example, since thread t1 operates on s1 and thread t2 operates on s2, there's nothing preventing the threads to be inside the synchronized block on the same time. The threads are using different locks. The mutual exclusion is determined by the lock instance, and not by the synchronized block, which only defines a scope.

于 2013-11-11T09:07:22.903 回答