我正在尝试学习同步。根据我学到的东西卡在这里下面的代码应该给8000作为最终结果,但我得到一个随机的结果如下 包线程;
import java.time.LocalDateTime;
public class A implements Runnable {
String name;
static Integer j=0;
A(String name){
this.name=name;
}
@Override
public synchronized void run() {
for(int i=1;i<=1000;i++){
synchronized(this){
A.j++;
}
}
System.out.println(j);
}
package threads;
public class MainClass {
public static void main(String args[]){
Thread t1=new Thread(new A("i am thread A "));
Thread t2=new Thread(new A("i am thread B "));
Thread t3=new Thread(new A("i am thread C "));
Thread t4=new Thread(new A("i am thread D "));
Thread t5=new Thread(new A("i am thread E "));
Thread t6=new Thread(new A("i am thread F "));
Thread t7=new Thread(new A("i am thread G "));
Thread t8=new Thread(new A("i am thread H "));
t1.setPriority(Thread.MAX_PRIORITY);
t8.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
t7.join();
t8.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
仍然得到像1293这样的输出 2214 1403 3214 4214 5214 6224 7037 任何人都可以向我解释如何实现同步以及这里出了什么问题?
答案 0 :(得分:12)
认为synchronized
表示“临界区”是一个常见的错误,并且在同步块运行时没有其他线程会运行。但是,同步块仅对于锁定在同一个锁上的其他同步块是独占的。
你得到的答案(“使用普通锁”)是正确的,但并没有真正告诉你原因。另一个常见错误是将synchronized
视为保护代码,而实际上您应该考虑保护数据。任何共享的可变数据都应该由一个且只有一个锁保护,您应该确切地知道该锁是什么。 (你的锁定方案越复杂,你就越不可能知道什么锁保护什么数据。)所以你应该总是考虑“数据X被锁L保护”,然后确保你每次获得锁L您访问(读取或写入)该数据。
答案 1 :(得分:5)
这将解决问题。由于要增加静态字段,因此必须synchronize
对所有线程使用共享锁。否则,每个对象将拥有它自己的锁并并行增加静态字段,从而导致竞争条件。这就是为什么你没有得到正确的值,在这种情况下是8000。
package bookmarks;
public class A implements Runnable {
String name;
static Integer j = 0;
private static Object lock = new Object();
A(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1; i <= 1000; i++) {
synchronized (lock) {
A.j++;
}
}
System.out.println(j);
}
}
答案 2 :(得分:1)
代码中存在一些问题。
问题1:synchronized(..)
中添加的锁定对象不在其中共享
所有线程实例
问题2:System.out.println(j);
行应该在t8.join();
之后结束,否则,您将获得8次输出。
经过纠正的代码
public class A implements Runnable {
String name;
static Integer j = 0;
static Object lockObject = new Object();
A(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1; i <= 1000; i++) {
synchronized (lockObject) {
A.j++;
}
}
}
public static void main(String args[]) {
Thread t1 = new Thread(new A("i am thread A "));
Thread t2 = new Thread(new A("i am thread B "));
Thread t3 = new Thread(new A("i am thread C "));
Thread t4 = new Thread(new A("i am thread D "));
Thread t5 = new Thread(new A("i am thread E "));
Thread t6 = new Thread(new A("i am thread F "));
Thread t7 = new Thread(new A("i am thread G "));
Thread t8 = new Thread(new A("i am thread H "));
t1.setPriority(Thread.MAX_PRIORITY);
t8.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
t7.join();
t8.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(A.j);
}
}