java同步问题

发布于 2024-07-27 13:58:52 字数 1559 浏览 8 评论 0原文

我遇到了 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();

    }
}

偶尔我会得到“在利比亚线程刚果很酷” 这绝对不应该发生。 我只期望: “利比亚主题利比亚真棒” “在刚果线程刚果很酷”

我不希望它们混合在一起。

I'm having issues with Synchronized not behaving the way i expect, i tried using volatile keyword also:

Shared Object:


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;
}
}

Thread 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();
    }
    }
}

Thread 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() );

    }
    }
}

Calling Class:


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();

    }
}

Occasionally i get "In Libya Thread congo cool"
which should never happen. I expect only:
"In Libya Thread libya awesome"
"In Congo Thread congo cool"

I dont expect them to be mixed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情深如许 2024-08-03 13:58:52

这些调用可以像下面这样交错:

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

The calls can interleave like the following:

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
一身仙ぐ女味 2024-08-03 13:58:52

这应该会给你带来你正在寻找的行为。

线程 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() );
            }
        }
    }
}

This should get you the behavior you're looking for.

Thread 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() );
            }
        }
    }
}

Thread 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() );
            }
        }
    }
}
洛阳烟雨空心柳 2024-08-03 13:58:52

对 getValue() 和 setValue() 的调用可能会交错。

也就是说,在另一个线程处于 getValue() 或 setValue() 状态的同时,不会有任何线程处于 getValue() 状态,同样,当另一个线程处于 getValue() 或 setValue() 状态时,也不会存在任何线程处于 setValue() 状态。

但是,不能保证单个线程将顺序调用 setValue() getValue() 而不被另一个线程抢占。

基本上,这是完全合法且可能的:

线程 1:v.setValue()
一些其他线程:任意数量的 v.getValue()'s/v.setValue()'s
线程1:v.getValue()

The calls to getValue() and setValue() may be interleaved.

That is, no thread will be in getValue() at the same time another thread is in getValue() or setValue() and likewise no thread will be in setValue() while another thread is in getValue() or setValue().

However, there's no guarantee that a single thread will make sequential calls to setValue() getValue() without being preempted by another thread.

Basically, this is perfectly legal and possible:

Thread 1: v.setValue()
Some Other Thread(s): Any number of v.getValue()'s/v.setValue()'s
Thread 1: v.getValue()

眼泪也成诗 2024-08-03 13:58:52

它可能是按这个顺序,所以它是正确的:

 v.setValue( "libya", "awesome" );
 //context switch
 v.setValue( "congo", "cool" );
 //context switch
 System.out.println("In Libya Thread " + v.getValue() );

因此你确实有某种意义上的竞争条件。 同步是每当您尝试调用同步方法时都会获取锁,因此您需要另一种方式来暗示对变量的同步访问。 例如,您可以从方法中删除同步并执行以下操作:

public void run() 
{
  for (int i = 0; i  10; i++) 
  {
   synchronized(v)
   {
      v.setValue( "caller", "value" );
      v.getValue();
   }
  }
}

It could be in this order so it's correct:

 v.setValue( "libya", "awesome" );
 //context switch
 v.setValue( "congo", "cool" );
 //context switch
 System.out.println("In Libya Thread " + v.getValue() );

Therefore you DO have a race conditions in some meaning. Synchronized is acquire a lock whenever you trying to call synchronized method, so you need another way to imply synchronized access to variable. For example you can remove synchronized from methods and do the following:

public void run() 
{
  for (int i = 0; i  10; i++) 
  {
   synchronized(v)
   {
      v.setValue( "caller", "value" );
      v.getValue();
   }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文