我遇到的问题是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 LibyaThread implements Runnable {
private ThreadValue v;
public LibyaThread(ThreadValue v) {
this.v = v;
}
public void run() {
for (int i = 0; i 10; i++) {
v.setValue( "libya", "awesome" );
System.out.println("In Libya Thread " + 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();
}
}
偶尔我会得到“在利比亚线程刚果酷” 这应该永远不会发生。我只期望: “在利比亚线程libya真棒” “在Congo Thread congo cool”
我不希望他们混在一起。
答案 0 :(得分:5)
调用可以像下面那样交错:
Thread 1 : v.setValue()
Thread 2 : v.setValue()
Thread 1 : v.getValue() // thread 1 sees thread 2's value
Thread 2 : v.getValue() // thread 2 sees thread 2's value
答案 1 :(得分:4)
这可以让你找到你正在寻找的行为。
主题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++) {
synchronized(v) {
v.setValue( "congo", "cool" );
System.out.println("In Congo Thread " + v.getValue() );
}
}
}
}
主题2:
class LibyaThread implements Runnable {
private ThreadValue v;
public LibyaThread(ThreadValue v) {
this.v = v;
}
public void run() {
for (int i = 0; i < 10; i++) {
synchronized(v) {
v.setValue( "libya", "awesome" );
System.out.println("In Libya Thread " + v.getValue() );
}
}
}
}
答案 2 :(得分:3)
它可能按此顺序,所以它是正确的:
v.setValue( "libya", "awesome" );
//context switch
v.setValue( "congo", "cool" );
//context switch
System.out.println("In Libya Thread " + v.getValue() );
因此,你有某种意义上的竞争条件。每当您尝试调用synchronized方法时,Synchronized都会获取一个锁,因此您需要另一种方式来暗示对变量的同步访问。例如,您可以从方法中删除synchronized并执行以下操作:
public void run()
{
for (int i = 0; i 10; i++)
{
synchronized(v)
{
v.setValue( "caller", "value" );
v.getValue();
}
}
}
答案 3 :(得分:3)
对getValue()和setValue()的调用可能是交错的。
也就是说,getValue()中没有线程同时另一个线程在getValue()或setValue()中,同样没有线程在setValue()中,而另一个线程在getValue()或setValue中( )。
但是,不能保证单个线程会对setValue()getValue()进行顺序调用,而不会被另一个线程抢占。
基本上,这是完全合法且可能的:
线程1:v.setValue()
其他一些线程:任意数量的v.getValue()/ v.setValue()的
线程1:v.getValue()