Java悲观锁与乐观锁

锁的目的

多线程编程如有共用资源的使用时,需要保证数据安全,资源需要同步处理。处理资源的手段可以有:互斥同步与非阻塞同步。实现分别对应:悲观锁与乐观锁。

实例

开20个线程进行计数,每个线程计算到10000。分别使用悲观锁与乐观锁来实现。

悲观锁实现

悲观锁是主要使用synchronized实现,通过锁住对应的对象,独占资源的方式。
demo实现代码如下:

import org.springframework.util.StopWatch;

public class ClassTestApplication {
    
    public static Integer i = new Integer(0);
    public static Object oj = new Object();//用于锁对象
    
    public static void main(String[] args) {
        StopWatch watch = new StopWatch();
        watch.start();
        for (int ac = 0; ac < 20; ac++) {
            Thread t1 = new Thread() {
                @Override
                public void run() {
                    for (int ac2 = 0; ac2 < 10000; ac2++) {
                        synchronized (oj) {//锁只能锁对象,不能锁值类型,所以需要另外新建oj对象
                            i = i + 1;
                            Thread.yield();//降低当前线程的优先级
                        }
                    }
                    System.out.println("i=" + i);
                    //输出时耗
                    if (i == 200000) {
                        watch.stop();
                        System.out.println("耗时:" + watch.getTotalTimeSeconds());
                    }
                }
            };
            t1.start();
        }
    }
}

输出结果如下:
i=20480
i=60223
i=71641
i=102771
i=103641
i=117543
i=127194
i=131049
i=140436
i=146951
i=153894
i=160899
i=162207
i=164290
i=170482
i=181676
i=189241
i=194425
i=198873
i=200000
耗时:0.1261655

乐观锁实现

乐观锁主要通过CAS(Compare and swap)去现实。
demo实现代码如下:

import org.springframework.util.StopWatch;
import java.util.concurrent.atomic.AtomicInteger;

public class ClassTest2Application {
    public static AtomicInteger j = new AtomicInteger();
    public volatile static int i;

    public static void main(String[] args) {
        StopWatch watch =new StopWatch();
        watch.start();
        for (int ac = 0; ac < 20; ac++) {
            Thread t1 = new Thread() {
                @Override
                public void run() {
                    for (int ac2 = 0; ac2 < 10000; ac2++) {
                        for (; ; ) { //自旋
                            Integer current = i;
                            Integer next = i + 1;
                            if (j.compareAndSet(current, next)) {  //对比并赋值,注意需要新建一变量current,不能直接使用i
                                i = next;
                                Thread.yield();//降低当前线程的优先级
                                break;
                            }
                        }
                    }
                    System.out.println("i=" + i);
                    if(i==200000)
                    {
                        watch.stop();
                        System.out.println("耗时:"+watch.getTotalTimeSeconds());
                    }
                }
            };
            t1.start();
        }
    }
}

输出结果如下
i=143289
i=146323
i=147099
i=150204
i=150598
i=155177
i=177143
i=184003
i=184685
i=187439
i=188419
i=189595
i=190235
i=192196
i=193054
i=194514
i=194798
i=198438
i=199530
i=200000
耗时:0.0482009

总结

这里只针对demo的场景做一下简单对比。

性能(好)可读性(好)复杂度(低)
乐观锁悲观锁悲观锁

PS:
1: synchronize 实际是多种锁组合,根据使用的情况,从 无锁->偏向锁->轻量级锁->重量级锁 。
2:因为测试的线程比较多,使用synchronize瞬间就升级为重量级锁。所以性能的对比还是可以的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值