我遇到的问题是Synchronized不按我期望的方式行事,我也尝试使用volatile关键字:
共享对象:
public class ThreadValue {
private String caller;
private String value;
public ThreadValue( String caller, String value ) {
this.value = value;
this.caller = caller;
}
public synchronized String getValue() {
return this.caller + " " + this.value;
}
public synchronized void setValue( String caller, String value ) {
this.caller = caller;
this.value = value;
}
}
主题1:
class CongoThread implements Runnable {
private ThreadValue v;
public CongoThread(ThreadValue v) {
this.v = v;
}
public void run() {
for (int i = 0; i < 10; i++) {
v.setValue( "congo", "cool" );
v.getValue();
}
}
}
主题2:
class CongoThread implements Runnable {
private ThreadValue v;
public CongoThread(ThreadValue v) {
this.v = v;
}
public void run() {
for (int i = 0; i < 10; i++) {
v.setValue( "congo", "lame" );
v.getValue();
}
}
}
致电班级:
class TwoThreadsTest {
public static void main (String args[]) {
ThreadValue v = new ThreadValue("", "");
Thread congo = new Thread( new CongoThread( v ) );
Thread libya = new Thread( new LibyaThread( v ) );
libya.start();
congo.start();
}
}
偶尔我会"In Libya Thread congo cool"
这应该永远不会发生。我只期望:
"In Libya Thread libya awesome"
"In Congo Thread congo cool"
我不希望他们混在一起。
答案 0 :(得分:1)
您只是分别同步getValue
和setValue
的访问权限而不是双线
v.setValue( "congo", ..);
v.getValue();
然后当然两个线程可以在一个setValue
和getValue
答案 1 :(得分:1)
接下来会发生什么:
为了解决这个问题,你需要有一个锁定对象来保护两个线程的get / set函数调用。执行此操作的最佳方法是创建一个同时执行set和get的同步方法。然而,有时这是不可取的。在这种情况下,给两个线程一个锁定对象。这只是一个普通的对象。然后他们在同步块中使用它。
每个线程的实现如下所示,请注意它们需要具有完全相同的对象!
Object lockObject = new Object();
Thread t1 = new CongroThread(v, lockObject);
Thread t2 = new LibyaThread(v, lockObject);
...
class CongoThread implements Runnable {
private ThreadValue v;
private Object lockObject;
public CongoThread(ThreadValue v, Object lockObject) {
this.v = v;
this.lockObject = lockObject,
}
public void run() {
for (int i = 0; i < 10; i++) {
synchronized(lockObject)
{
v.setValue( "congo", "lame" );
v.getValue();
}
}
}
}
答案 2 :(得分:0)
您是否同步了System.out.println调用?如果没有同步,它们是线程安全的,但可能无法以正确的顺序发出。
synchronzied(System.out) {
System.out.print(....);
System.out.flush();
}