[转]关于ReentrantLock中线程读某个变量是否需要加锁
2017-06-07 17:30
302 查看
我在使用ReentrantLock类对变量进行多线程累加时,调用了lock()和unlock()方法,但读取该变量时我未加锁,结果是能正确执行,代码如下:
Java代码
public class Main {
private long count;
private ExecutorService pool;
private Lock lock = new ReentrantLock();
/**
* @param args
*/
public static void main(String[] args) {
new Main().countThread();
}
public Main() {
pool = Executors.newFixedThreadPool(50);
}
public void countThread() {
for (int i = 0; i < 3000; i++) {
pool.execute(new Runnable() {
@Override
public void run() {
lock.lock();
try {
count++;
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
}
while (true) {
System.out.println(count);
if (count == 3000) {
break;
}
}
System.out.println(count);
pool.shutdown();
}
}
http://www.infoq.com/cn/articles/java-memory-model-1 这篇文章介绍了Java内存模型定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。
能不能这样理解,类中的全局变量是存储在主内存。也就是读操作不需要锁,不知道理解是否正确。
合理解释:
主存的变量,线程的本地内存会有一个副本这没错.可是两者有一个同步时机的问题,所以你这样用是不安全的.
要么两边都同步保护,要么你增加"volatile"关键字提示这个变量不能创建本地副本.
Java代码
public class Main {
private long count;
private ExecutorService pool;
private Lock lock = new ReentrantLock();
/**
* @param args
*/
public static void main(String[] args) {
new Main().countThread();
}
public Main() {
pool = Executors.newFixedThreadPool(50);
}
public void countThread() {
for (int i = 0; i < 3000; i++) {
pool.execute(new Runnable() {
@Override
public void run() {
lock.lock();
try {
count++;
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
}
while (true) {
System.out.println(count);
if (count == 3000) {
break;
}
}
System.out.println(count);
pool.shutdown();
}
}
http://www.infoq.com/cn/articles/java-memory-model-1 这篇文章介绍了Java内存模型定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。
能不能这样理解,类中的全局变量是存储在主内存。也就是读操作不需要锁,不知道理解是否正确。
合理解释:
主存的变量,线程的本地内存会有一个副本这没错.可是两者有一个同步时机的问题,所以你这样用是不安全的.
要么两边都同步保护,要么你增加"volatile"关键字提示这个变量不能创建本地副本.
相关文章推荐
- C# 在两个不同的方法里面Lock同一个锁对象,是否需要线程等待?
- 关于环境变量设置是否需要重启的问题
- 变量线程安全之ReentrantLock
- 关于某个变量线程是否安全问题的根本回答
- 关于as3.0代码里delete后是否需要null
- 关于链式队列是否需要头结点
- 关于ubuntu 是否需要使用std::到问题。
- 关于IDE、ATA、SATA、PATA及SATA硬盘安装xp是否需要SATA驱动问题的解释说明
- 线程同步中的变量因需要其他的线程对这个变量进行改变
- shell中ssh语句里的变量一定要注意是否需要转义
- 关于static变量的线程间共享,进程间不共享
- 关于ReentrantReadWriteLock两个问题及解决心得(转)
- 关于static变量的线程间共享,进程间不共享
- 开启服务器,自动加载类是否需要开辟新的线程研究
- 开启服务器,自动加载类是否需要开辟新的线程研究
- 关于链式队列是否需要头结点
- Java-关于子类是否继承了父类的private实例变量
- 多线程中对全局变量(整型类型)是否需要同步操作
- ActiveX关于“此网页需要运行以下加载项:"xxx" 的 "xxx" ” 是否允许的询问
- Java中使用ReentrantLock控制线程执行顺序