使用同步方法的问题
Issues on using synchronized method
我试图了解同步,但在尝试实现它时,我得到了一个模棱两可的结果,在尝试实现同步时,请看一下。
通过观察输出,很明显两个线程能够同时访问同步块。指导我哪里错了。
输出:
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.Whosebug.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
By obesrving the output, it is clear that two threads are able to access the synchronized block simultaneously.
不,绝对没有证据表明这一点。让我们考虑以下输出:
Display class show method called by- Thread-0
Display class show method called by- Thread-1
这里:
Thread-0
调用show()
,进入synchronized
块,打印消息,退出show()
(离开synchronized
块)。
Thread-1
调用show()
,进入synchronized
块,打印消息,退出show()
(离开synchronized
块)。
等等。
如果您想看到线程相互阻塞,请将 synchronized
放在循环周围:
synchronized(d) {
for (int i = 0; i < 10; i++) {
d.show();
}
}
你的同步块没有被并发访问。
您观察到的是:
- Thread-0 进出 7 次
- Thread-1 进出 10 次
- Thread-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次,那么你应该在for-loop
:
周围使用synchronized
@Override
public void run() {
showSeveralTimes(10);
}
在Display
中:
synchronized void showSeveralTimes(int n) {
for(int i = 0 ; i < n ; ++i) {
show();
}
}
引用自 Oracle tutorial:
- First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
- Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
所以 Thread-n
运行,returns,Thread-n
运行,returns,无限循环(在这种情况下为 10)
我试图了解同步,但在尝试实现它时,我得到了一个模棱两可的结果,在尝试实现同步时,请看一下。
通过观察输出,很明显两个线程能够同时访问同步块。指导我哪里错了。
输出:
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.Whosebug.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
By obesrving the output, it is clear that two threads are able to access the synchronized block simultaneously.
不,绝对没有证据表明这一点。让我们考虑以下输出:
Display class show method called by- Thread-0
Display class show method called by- Thread-1
这里:
Thread-0
调用show()
,进入synchronized
块,打印消息,退出show()
(离开synchronized
块)。Thread-1
调用show()
,进入synchronized
块,打印消息,退出show()
(离开synchronized
块)。
等等。
如果您想看到线程相互阻塞,请将 synchronized
放在循环周围:
synchronized(d) {
for (int i = 0; i < 10; i++) {
d.show();
}
}
你的同步块没有被并发访问。
您观察到的是:
- Thread-0 进出 7 次
- Thread-1 进出 10 次
- Thread-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次,那么你应该在for-loop
:
synchronized
@Override
public void run() {
showSeveralTimes(10);
}
在Display
中:
synchronized void showSeveralTimes(int n) {
for(int i = 0 ; i < n ; ++i) {
show();
}
}
引用自 Oracle tutorial:
- First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
- Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
所以 Thread-n
运行,returns,Thread-n
运行,returns,无限循环(在这种情况下为 10)