目录
一、线程安全
线程安全:就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
二、保证线程安全
1.使用线程安全的类,例如:CopyOnWriteArrayList、ConcurrentHashMap等;
2.使用synchronized同步锁、或者Lock锁。
三、synchronized 和 Lock 的区别
两者都是可重入锁。
区别:
1. synchronized 是一个关键字,依赖于JVM的底层实现。
Lock 是一个接口,依靠实现类来实现它的功能(常用实现类:ReentrantLock)
2. 写法不同
Lock :
Lock lock = new ReentrantLock();
public void suo(){
lock();
//可能发生线程安全问题的代码
unlock();
}
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Runnable r = new Runnable() {
@Override
public void run() {
lock.lock();
try{
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}finally{
lock.unlock();
}
}
};
Thread t1 = new Thread(r,"A");
Thread t2 = new Thread(r,"B");
t1.start();
t2.start();
}
synchronized :
修饰代码块:
synchronized(){
//有可能发生线程安全问题的代码
}
public static void main(String[] args) {
Object obj = new Object();
Runnable r = new Runnable() {
@Override
public void run() {
//synchronized代码块
synchronized(obj) {
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
};
Thread t1 = new Thread(r,"A");
Thread t2 = new Thread(r,"B");
t1.start();
t2.start();
}
修饰方法:
public synchronized void A(){
//有可能发生线程安全问题的代码
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
A();
}
};
Thread t1 = new Thread(r,"A");
Thread t2 = new Thread(r,"B");
t1.start();
t2.start();
}
public static synchronized void A() {
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
3. synchronized:只能是非公平锁,可以自动释放锁
Lock:可以是公平锁,可以是非公平锁,必须手动释放锁
四、使用场景
如果没有一些特别的需求:使用synchronized方式,内置关键字,使用方便
比较特殊的需求:使用Lock
五、好好学习,天天向上
good good study , day day up!