多线程问题volatile Synchronise Lock and AtomicReference
以前用到的关于锁和线程安全注意的地方比较少,最近项目出现一些公用内容需保证线程安全所以采用AtomicReference 和concurrentMap,
顺便再梳理了下线程安全的内容:
从性能上来说AtomicReference比synochronizd 和 Lock要好得多。
下面来看下一些实现:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTask implements Runnable {
private int lockVariable;
private Lock lock;
public LockTask() {
this.lockVariable = 0;
this.lock = new ReentrantLock();
}
@Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
lock.lock();
lockVariable = i;
lock.unlock();
}
}
}
public class SecuritySingleton {
private static SecuritySingleton securitySingleton;
private SecuritySingleton(){};
static synchronized SecuritySingleton getInstance(){
if(securitySingleton==null){
securitySingleton = new SecuritySingleton();
}
return securitySingleton;
}
}
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicTask implements Runnable {
private final AtomicInteger variableInt;
public AtomicTask() {
this.variableInt = new AtomicInteger(0);
}
@Override
public void run() {
for (int i = 0; i < 1000000000; i++) {
variableInt.set(1);
}
}
}
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
public class AtomicService {
private final AtomicReference<Map<String, String>> areaMapping = new AtomicReference<>();
private AtomicService() {
this.areaMapping.set(new ConcurrentHashMap());
}
public void addValue(String key, String value) {
areaMapping.get().put(key, value);
}
public String getValue(String key) {
return areaMapping.get().get(key);
}
}
摘抄自博客:https://www.cnblogs.com/caiba/p/10616615.html
synochronizd和volatile关键字区别:
1. volatile关键字解决的是变量在多个线程之间的可见性;而sychronized关键字解决的是多个线程之间访问共享资源的同步性。
2. volatile只能用于修饰变量,而synchronized可以修饰方法,以及代码块。(volatile是线程同步的轻量级实现,所以volatile性能比synchronized要好,并且随着JDK新版本的发布,sychronized关键字在执行上得到很大的提升,在开发中使用synchronized关键字的比率还是比较大)
3. 多线程访问volatile不会发生阻塞,而sychronized会出现阻塞。
4. volatile能保证变量在多个线程之间的可见性,但不能保证原子性;而sychronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公有内存中的数据做同步。
线程安全包含原子性和可见性两个方面。
对于用volatile修饰的变量,JVM虚拟机只是保证从主内存加载到线程工作内存的值是最新的。
一句话说明volatile的作用:实现变量在多个线程之间的可见性。
synchronized和lock区别
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率(读写锁)。
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
浙公网安备 33010602011771号