3 回答
TA贡献1856条经验 获得超17个赞
Java Integer 不能通过引用传递。在您的代码中,每个线程都会创建变量的副本。但是 atomicInteger 可以通过引用传递。
此外,为了获得正确的结果,您可以将 num 变量更改为静态变量。
public static Integer num = 1;
public Object lock;
public ThreadDemo(Integer num, Object lock) {
//this.num = num;
this.lock =lock;
}
TA贡献1825条经验 获得超6个赞
仅就您的知识而言,您可能希望尝试使用(s) (例如) 及其相关联的 (s),而不是在 上使用synchronized
块。Object
Lock
ReentrantLock
Condition
使用Condition
(s) 您可以在线程之间以互斥的方式管理共享资源。
TA贡献2041条经验 获得超4个赞
我仍然认为这个问题没有得到正确回答。这里的缺陷是您从未将共享数据标记为static. 所以每个线程都有自己独立的副本。Integer是一个不可变的包装类,这是真的,但在这种情况下它没有任何关系。让我们深入研究一下num++。该++运算符仅适用于(原始)整数类型。在幕后,num拆箱,++应用,然后将结果分配回num(在装箱转换之后)。该类Integer没有++运算符。事实上,Integer对象是不可变的。
不可变意味着每次你增加并创建一个新的值对象。并且该新值对象被分配回您的num引用。但是两个线程有自己的num引用副本,指向不同的Integer盒装原语。因此,它们彼此独立地增加它,而彼此不可见。如果你想在线程之间共享它,你必须static在声明的地方使用访问修饰符。将两个值传递给共享变量是没有意义的。相反,您可以内联初始化它。这是固定版本。
public class ThreadDemo implements Runnable {
public static Integer num = 1;
public static final Object lock = new Object();
public ThreadDemo() {
}
@Override
public void run() {
try {
while (true) {
int count = 0;
synchronized (lock) {
Thread.sleep(100);
while (count < 2) {
System.out.println(Thread.currentThread().getName() + " " + num++);
count++;
}
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CoWorkingThreads {
public static void main(String[] args) {
Thread thread1 = new Thread(new ThreadDemo(), "First");
thread1.start();
Thread thread2 = new Thread(new ThreadDemo(), "Second");
thread2.start();
}
}
最后使用客户端提供的锁对象违反了同步策略的封装。所以我改用了内部私有锁对象。
这是新的输出。
第一 1 第一 2 第二 3 第二 4 第一 5 第一 6 第二 7 第二 8 第一 9 第一 10
添加回答
举报