1

我正在上一门关于 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

每次电流值的顺序明显不同。

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

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

4

3 回答 3

6

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

您没有得到预期的顺序,因为创建了 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.

永远无法保证线程将以何种顺序执行该方法

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

于 2013-06-12T05:55:54.610 回答
3

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

于 2013-06-12T05:54:59.150 回答
3

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

于 2013-06-12T05:55:47.863 回答