【问题标题】:Java Synchronized Method on Static Variable静态变量上的 Java 同步方法
【发布时间】:2013-06-12 05:46:22
【问题描述】:

我正在上一门关于 Java 并发的大学课程,最近得到了一个简单的任务,即创建 5 个编号从 1 到 5 的线程,然后让每个线程使用同步静态将其线程号写入类中的静态变量方法。

讲师给我的解决方案如下:

public class thread1 extends Thread {

private int threadNumber;
private static int threadCount = 0;
private static int value;

public thread1(){
      threadNumber = ++threadCount;
      System.out.println("Thread " + threadNumber + " is created" );
}

public synchronized static void setValue(int v){
      value = v;
      try{
           Thread.currentThread().sleep(100);
      }
           catch(InterruptedException e ){}

      System.out.println("the current value of the variable is " + value);
}

public void run() {
    setValue(threadNumber);
    return;
}

public static void main(String[] args) {
    for(int i = 0; i < 5; i++){
        thread1 thr = new thread1();
        thr.start();
}

}
}   

输出应该如下:

创建线程 1
创建线程 2
创建线程 3 已创建
线程 4 已创建
线程 5 已创建
变量的当前值为 1
的当前值 变量为 2
变量的当前值为 3
变量的当前值为 4
的当前值 变量为 5

但我得到的输出如下:

创建线程 1
线程 2 已创建
线程 3 已创建
线程 4 已创建
创建线程 5
变量的当前值为 1
变量的当前值为 5
的当前值 变量为 4
变量的当前值为 3
变量的当前值为 2

每次当前值的顺序明显不同。

我得到的解决方案不正确吗?它显然无法实现其预期目的,即按顺序打印出每个线程的 value 变量。

谁能解释一下我如何让它每次可靠地按从 1 到 5 的顺序打印线程号?我认为使用同步的 setValue 方法可以解决问题,但显然不是。

【问题讨论】:

  • synchronized 只是防止多个线程同时进入方法;它没有说明他们输入的顺序。
  • 查看 ExecutorService.invokeAll 方法和这里的帖子stackoverflow.com/questions/3741765/…
  • 使用join()按顺序获取输出

标签: java multithreading concurrency synchronized


【解决方案1】:

你的讲师提供的解决方案是绝对正确的。

您没有得到预期的顺序,因为创建了 5 个不同的线程,并且每个线程都必须访问相同的同步方法。

当一个方法同步时,一次只有一个对象可以访问它

在您的情况下,只有 一个线程可以访问 setValue 方法

when one Thread enters the method it acquires the lock and 
the other threads wait for the lock ,when this Thread releases the lock , 
any waiting Thread can acquire it and execute the setValue method.

您可以从不保证线程将执行该方法的顺序

所以你每次运行这个程序时都会得到一些不同的线程顺序

【讨论】:

    【解决方案2】:

    无法保证线程将按照您对其调用 start 方法的顺序执行。 同步块仅意味着两个线程不能同时访问它。线程运行的顺序由调度程序决定。

    【讨论】:

      【解决方案3】:

      线程进入监视器的顺序没有定义。一旦一个线程在监视器内完成执行,任何其他在该监视器上等待的线程都可以控制临界区。

      【讨论】:

        猜你喜欢
        • 2016-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多