java中的同步块

时间:2015-07-29 19:31:24

标签: java synchronization

class Call {
  int count;

  public   void  increment() {
    for (int i = 0; i < 1000; i++)
        count++;
  }
}

class Caller implements Runnable {

  Call c;

  public Caller(Call c) {
    this.c = c;
  }

  @Override
  public void run() {
    // TODO Auto-generated method stub
        c.increment();
  }
}

class Calling implements Runnable {

  Call c;

  public Calling(Call c) {
    this.c = c;
  }

  @Override
  public void run() {
    // TODO Auto-generated method stub
    synchronized (c) {
        c.increment();
    }
  }
}

public class SynchronizedBlock {

  public static void main(String[] args) throws InterruptedException {
    Call call = new Call();
    Calling calling = new Calling(call);
    Caller caller = new Caller(call);

    Thread t1 = new Thread(caller);

    Thread t2 = new Thread(calling);
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println("caller:" + caller.c.count);
  }
}

这里已经使增量方法在1个类中同步,而在其他类中我没有使它成为同步的。当我运行上面的代码时,它有时会给出小于2000的计数值。

根据我的理解,由于Calling类的对象已经锁定了对象,因此不需要在Caller类的increment方法中进行同步。

请你帮我理解这里的逻辑。

3 个答案:

答案 0 :(得分:1)

  

由于Calling类的对象已经锁定了对象,所以就在那里   无需在Caller类增量方法中进行同步。

您的理解不正确。为了使变量上的并行操作具有确定性,您必须在每个访问/修改该变量**时进行某种同步。

您还需要synchronize中的Caller

**:这是确保确定性的必要但不充分的条件。

答案 1 :(得分:1)

java中的

increment关键字表示在进入块之前获取锁定并在退出后释放。

由于 t2 获取/释放锁定而 t1 没有,因此实际上没有同步进行。每当分配CPU时间时, t1 就进入块中。

t2 也总是在没有等待的情况下进入块中,因为 t1 永远不会获取锁。

-

如果您同步class Call { int count; public synchronized void increment() { for (int i = 0; i < 1000; i++) count++; } } 方法,您的程序将正常工作:

var cmd = words.Where(c => c.Text == command).First();

完成此更改后,您可以从 t2 中删除同步块。

答案 2 :(得分:0)

当你得到import java.io.*; public class Nth_Prime { public static void main()throws Exception { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Which Prime number would you like to find?"); int n = Integer.parseInt(stdin.readLine()); int k = 0; int counter = 1; int num=0; for(int i=3;i<100;i++) { k=0; for(int j=2;j<i;j++) { if(i%j!=0) { k++; } } if(k!=0) { num=i; counter++; } if(counter==n) { System.out.println("The number is: "+num); break; } } } } 的正确值时,可能发生的事情发生在这些行之间:

2000

这是因为在t1.start(); t2.start(); 行执行之前,public void increment();的执行在一个量子中完成。 Thread Quantum是线程在不同线程可以在处理器核心上运行之前运行的时间。

第一个线程没有锁定对象,偶尔单个量程不会包含t2.start()的整个执行,这为线程2留出时间开始执行并处理相同的对象数据。这将导致同时存在2个变量increment()副本,争夺相同的内存。

尝试将增量count增加到某个数字for (int i = 0; i < 1000; i++)。您很可能会更频繁地看到应用程序开始失败。