public class Counter {
private volatile int count = 0; //若要线程安全执行执行count++,需要加锁
public synchronized void increment() {
count++;
} public int getCount() { return count;
}}为什么 这种自增 需要 加锁, 我理解为 没有 使用他对象 都有自己的 count , 完全不会影响他 其他 对象啊除非用 static 的,请 大牛 们 帮忙解释下。谢谢
解决方案 »
- JFrame在去掉标题栏的情况下怎么实现拉大收缩边框的功能?
- 问个关于jre的问题
- 根据起始IP地址和结束IP地址,计算子网掩码,有一种情况会出现死循环,找不到原因何在
- 求一算法
- 从数据库中取得多字段的list,怎样查询出所要知道的结果?
- 各位JBuilder剑侠客,请问如何加载Jbuilder Tool page,就象swing page一样,显示一些工具……
- 如何用java实现用户权限的管理
- 在forte for java 4的Source Editor中编辑jsp时候,可以输入中文,可是保存后关闭再打开,中文显示???,怎么回事啊
- 这是哪个地方出错了?
- Sun 公司去死。。。
- socket 聊天程序 急急急!!!
- 关于java取出或插入大量数据时outof memory exeception
private int count = 0; //若要线程安全执行执行count++,需要加锁
public synchronized void increment() {
count++;
} public int getCount() { return count;
}}
public ServerThread(Vector<ServerThread> threads) {
} public void run(){}
// 将c实例赋值给 t2 线程的某个域线程中 run方法内有调用increment()方法不锁就会有问题 (++操作不是原子的。 说错了,高手请指出啊= =)
锁了就没问题
Ps: 在这个场合,给count加上volatile也是不恰当的。如果你的每个线程都有自己独立的一个Counter对象,那无需加锁。如果多线程共享一个Counter对象,就必须加锁。
随便举个例子
假设类A中定义了static Counter c;在多个线程中都有调用A.c.increment()
随便怎样都有可能啊工作线程需要一个Counter类实例作为他的成员,
那么线程需要调用某个方法将这个实例赋值给他的成员吧~这样就可能两个线程公用一个Counter实例当然,可能你的Counter类并不是这个用法,但的确是存在不加锁会出问题的可能具体还是看这个类的职责是什么,有无线程同步的需求如果这个类根本不可能被多线程使用,那么就不需要加锁
public class Counter {
private volatile int count = 0;
//若要线程安全执行执行count++,需要加锁
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}class MyTask implements Runnable{
private Counter counter;
public MyTask(Counter counter) {
this.counter = counter;
}
public void run() {
counter.increment();
}
}class Concurrent{
public static void main(String[] args) {
/*
* thread1 和 thread2 同时对一个 counter 进行操作。这种情况下,counter 需要注意线程安全问题
*/
Counter counter = new Counter();
Thread thread1 = new Thread(new MyTask(counter));
thread1.start();
Thread thread2 = new Thread(new MyTask(counter));
thread2.start();
}
}
反之就不需要,甚至连volatile都可以省了……
1,如果没有 volatile,那么如果线程 A 频繁访问 count,编译器很可能优化其为寄存器,这时线程 B 修改了 count,A 当时是无反应的,此时 A 再修改,B 的修改就被覆盖了。2,加锁也是必须的,因为两个 CPU 同时对一个地址写,也是可能覆盖情况。
针对这个情况 CPU 提供了互斥指令,这个互斥指令可以阻止另外的 cpu 对某地址进行同时访问,就是“无锁”的根本依赖,即 windows 提供的 interlocked 系列函数
public synchronized void increment() 会被多个线程同时调用
而用锁是不想出现两个线程同时 increment 而结果却只加1的情况
直接 InterlockedIncrement
这个回答很到位。count值用volatile修饰,在多线程中必须的原因,跟Java的内存模型有关(可以参考《Java多线程设计模式详解》一书的附录B Java的内存模型)。具体原因是,每个线程对内存的值都有一个拷贝(也就是线程运行的时候,先要从内存中把相应的值拷贝到工作存储器上),如果没有volatile,或者acychronize等关键词的修饰,各个线程在修改值的时候,就不会保证值的一致性。所以上面的cout用volatile修饰不是应为原子性的问题,而是由于java内存模型决定的。volatile能够保证count在各个线程中的一致性。
内存模型在《Java多线程设计模式详解》一书中有个经典的比喻:主存储器好比是大家看到的黑板;而工作存储器则像是每个人的笔记本。