又要线程安全,又要同时执行,怎么办?
悲观锁:一上来就加锁,没有安全感。每次只能一个线程进入访问完毕后,再解锁。线程安全,性能较差
乐观锁:一开始不加锁,认为是没有问题的,大家一起跑,等要出现线程安全的时候才开始控制。线程安全,性能较好
案例:创建一百个线程,每个线程对一个变量自增100次
悲观锁
public class ThreadTest {
public static void main(String[] args) {
Runnable target = new MyRunnable();
for (int i = 0; i < 100; i++) {
new Thread(target).start();
}
}
}
public class MyRunnable implements Runnable{
private int count;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
synchronized (this) {
count ++;
System.out.println(Thread.currentThread().getName() + "count----->" + count);
}
}
}
}
乐观锁(CAS算法)
使用乐观锁进行整数自增时,用原子对象
public class MyRunnable2 implements Runnable{
private AtomicInteger count = new AtomicInteger();
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "count----->" + count.incrementAndGet());
}
}
}
乐观锁是一种并发控制策略,用于解决多个线程或进程同时对同一资源进行修改的并发冲突问题。它的原理是通过在数据记录中引入一个版本号或时间戳来判断是否存在冲突。
具体来说,当一个线程要修改某个数据记录时,它首先会读取该记录的当前版本号或时间戳,并将其保存下来。然后,在修改完成后,线程会再次读取该记录的版本号或时间戳,并将之前保存的值与当前值进行比较。如果两者相等,表示在整个修改过程中没有其他线程对该记录进行修改,那么当前线程的修改被认可并生效。如果两者不相等,表示在修改过程中有其他线程对该记录进行了修改,那么当前线程的修改被认为是无效的,需要进行相应的处理(例如重新读取最新的数据进行修改)。
使用乐观锁可以减少锁的使用,提高并发性能,但也可能引发冲突问题。当多个线程同时读取同一数据记录时,都会认为自己是唯一的修改者,从而可能导致数据的不一致性。因此,在使用乐观锁时需要注意处理冲突问题,例如通过重试机制或回滚操作来解决。