Java线程共享对象同步问题
我发现Synchronized的行为与我预期的不一致,我尝试使用volatile关键字: 共享对象:Java线程共享对象同步问题,java,multithreading,volatile,synchronized,Java,Multithreading,Volatile,Synchronized,我发现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 S
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();
}
}
偶尔我会说“在利比亚很酷”
这是不应该发生的。我只希望:
“在利比亚,这太棒了”
“在刚果,刚果很酷”
我不希望它们是混合的。问题是,利比亚线程的v.getValue()可能在刚果线程调用v.setValue()之后立即被调用,从而导致您的混淆
解决方案是让一个线程同时阻塞get和set值,否则您将继续遇到这个问题。您必须在setter内部调用getter,或者使用wait/notify让另一个线程等待,直到一个线程同时设置并获取了值。为什么它们不能混合使用?尽管每个单独的调用都是同步的,但是没有什么可以阻止一个线程调用v.setValue,然后另一个线程调用setValue,然后第一个线程调用getValue()。我相信这就是正在发生的事情。您可以使用以下方法避免此问题:
public void run() {
for (int i = 0; i 10; i++) {
synchronized (v) {
v.setValue( "libya", "awesome" );
System.out.println("In Libya Thread " + v.getValue() );
}
}
}
这样,在每次迭代中,它确保调用setValue
和getValue
,而同时没有另一个线程调用setValue
诚然,这不是一个理想的设计——但我猜这个演示更能理解同步:)发生了以下情况:
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( "libya", "awesome" );
System.out.println("In Libya Thread " + v.getValue() );
}
}
}
}
对象锁定对象=新对象();
线程t1=新的Congreothread(v,lockObject);
线程t2=新的LibyaThread(v,lockObject);
...
类CongoThread实现可运行{
私有价值v;
私有对象;
public CongoThread(线程值v,对象锁定对象){
这个,v=v;
this.lockObject=lockObject,
}
公开募捐{
对于(int i=0;i<10;i++){
已同步(锁定对象)
{
v、 setValue(“利比亚”,“很棒”);
System.out.println(“In-Thread”+v.getValue());
}
}
}
}
锁定“真实”对象通常是不好的做法。使用一个单独的对象来锁定,这个对象应该只用于锁定一个特定的功能。是的,我同意。。。我希望这只是一个教学例子。和的重复已经被回答了多次。@Bombe第二个“重复”就是这个问题