我正在做一个关于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次的顺序打印线号?我认为使用synchronized setValue 方法可以解决问题,但显然不行。
答案 0 :(得分: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.
您可以永远不保证线程将以何种顺序执行方法,
因此,每次运行此程序时,您将获得一些不同的线程顺序
答案 1 :(得分:3)
无法保证线程将按照您对其调用start方法的顺序执行。 同步块仅表示两个线程无法同时访问它。要运行的线程的顺序由scheduler确定。
答案 2 :(得分:3)
未定义线程进入监视器的顺序。一旦线程在监视器内完成执行,在该监视器上等待的任何其他线程都可以获得对关键部分的控制。