使用同步方法的问题

时间:2015-01-07 14:46:59

标签: java synchronization

我试图理解同步,但是当它试图实现它时,我得到一个模糊的结果,同时尝试实现synchronized,看看它。

通过观察输出,很明显两个线程能够同时访问同步块。指导我哪里出错了。

输出:

Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0

计划:

package com.StackOverFlow.Doubts3;

public class Dbts5 {
public static void main(String[] args) {

    Display d1= new Display();
    MyThreads th1= new MyThreads(d1, "Thread1");

    th1.start();

    MyThreads th2= new MyThreads(d1, "Thread2");

    th2.start();




}
}

class MyThreads extends Thread{


Display d;
String name;


@Override
public void run() {
    super.run();
    for (int i = 0; i < 10; i++) {
        d.show();   
    }



}

public MyThreads() {}

MyThreads(Display d, String name){
    this.d=d;
    this.name=name;
}


}

class Display{

synchronized void show(){
    System.out.println("Display class show method called by- "+Thread.currentThread().getName());
    try {
        Thread.currentThread().sleep(300);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
}

(编辑)的 预期产出:

Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
.
.
.
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1

3 个答案:

答案 0 :(得分:2)

  

通过观察输出,很明显两个线程能够同时访问同步块。

不,绝对没有证据证明这一点。让我们考虑以下输出:

Display class show method called by- Thread-0
Display class show method called by- Thread-1

下面:

  • Thread-0调用show(),输入synchronized块,打印出消息,退出show() (离开synchronized } block。。
  • Thread-1调用show(),输入synchronized块,打印出消息,退出show() (离开synchronized } block。。

等等。

如果您希望看到线程相互阻塞,请将synchronized放在循环周围:

synchronized(d) {
    for (int i = 0; i < 10; i++) {
        d.show();   
    }
}

答案 1 :(得分:2)

不同时访问同步块。

您观察到的是:

  • 线程-0进出7次
  • 线程-1进出10次
  • 线程-0进出3次

如果你添加一些跟踪,你会发现在退出之前从未输入show两次更好:

synchronized void show(){
    System.out.println(Thread.currentThread().getName() + " In");
    // do show
    System.out.println(Thread.currentThread().getName() + " Out");
}

你会看到:

Thread-0 In
Display class show method called by- Thread-0
Thread-0 Out
// ...
Thread-1 In
Display class show method called by- Thread-1
Thread-1 Out
// ...
Thread-0 In
Display class show method called by- Thread-0
Thread-0 Out

如果您希望线程在释放锁定之前调用show n次,那么您应该在synchronized周围使用for-loop

@Override
public void run() {
    showSeveralTimes(10);
}

Display

synchronized void showSeveralTimes(int n) {
    for(int i = 0 ; i < n ; ++i) {
        show();
    }
}

答案 2 :(得分:0)

引用Oracle tutorial

  
      
  • 首先,对同一对象的两个同步方法的调用不可能进行交错。当一个线程正在为一个对象执行一个synchronized方法时,所有其他线程都会调用同一个对象的同步方法(暂停执行),直到第一个线程完成该对象为止。
  •   
  • 其次,当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立一个先发生关系。这可以保证对所有线程都可以看到对象状态的更改。
  •   

所以Thread-n运行,返回,Thread-n运行,返回,无限广告(在这种情况下为10)