包教包会Cas无锁机制-手写无锁机制Lock锁

1.现在有这么一个问题10个线程对一个全局变量进行赋值就是i++嘛 每个线程赋值1000次 最后打印结果是几

  结果是10*1000等于一万对吗?下面是代码测试。

package com.hd.jxd;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DemoLock {
   int i=0;
    public void incr(){
             i++;
    }

    public static void main(String[] args) {
        DemoLock demoLock=new DemoLock();
        for (int i = 0; i <10 ; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 1000; j++) {
                        demoLock.incr();
                    }
                }
            }).start();
        }

        try {
            Thread.sleep(1000);//休息一下等待线程全部执行完在打印不然会执行完一半就没有意思了
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(demoLock.i);
    }


}
代码给你们写好了直接复制粘贴测试一下打印结果为8641是一个小于一万的数(每次测试不一定是这个结果,但是一定小于一万)

原因是当其中一个线程在内存中拿到结果,对其进行赋值的时候其实其他线程已经在内存中把他修改了,就好比一个小姐姐要嫁妆说好10万块钱,谁出的高嫁给谁,当你准备好11万的时候,人家土豪已经把11万给他它了,更欺负人的是你过来开的时候小姐姐都已经是12万了,(小姐姐代表内存)。

如果想再深入解请看CAS无锁机制必须了解的JVM内存模型这篇文章下边是链接绝对收获满满

https://blog.csdn.net/weixin_39831786/article/details/88379024

这怎么办你可以加synchronized关键字给他加锁,但是我们现在不用这种方法,用一种无锁机制来解决,首先说你加synchronized代表什么,还是拿刚才那个例子举例,你说好10万嫁妆娶人家小姐姐,但是你害怕再有土豪捣乱,你直接把小姐姐锁在一个屋子里与外界隔绝谁都不见,直到你把10万拿来美滋滋的娶人家。这样首先会丧失效率,对人家小姐姐也不公平。

那怎么办,我们用一个Lock锁解决看下边代码

package com.hd.jxd;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public  class DemoLock {
   int i=0;

    Lock lock=new ReentrantLock();
    
    public  void incr(){

        lock.lock();//上锁

         try {
             i++;
         }finally {
             lock.unlock();//解锁
         }

    }

    public static void main(String[] args) {
        DemoLock demoLock=new DemoLock();
        for (int i = 0; i <10 ; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 1000; j++) {
                        demoLock.incr();
                    }
                }
            }).start();
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(demoLock.i);
    }


}
打印结果为1万 看了嘛,代码给你们写好直接粘贴试一下
Lock lock=new ReentrantLock();
lock.lock();
lock.unlock();
就加了这三行完美解决,效率完全碾压synchronized

我说一下原理,它是一种Cas无锁机制,java通过一个unsafe类直接访问内存,然后在内存中拿到值进行比较,如果发现不对,先改正之后进行赋值,‘

还是拿刚才那个例子。小姐姐和你说好了10万块钱,因为有土豪的捣乱不断被修改,那怎么办,你学精了我在找小姐姐送嫁妆的时候我先问一下,你现在多少钱嫁人了,(小姐姐代表内存)他说11万了,你说卧槽好吧我改11万然后加一万12万给你行了吧。看源码:

 

这个valueOffset就是通过unSafe类直接访问内存拿到小姐姐现在的报价,except是你期望的值本来是说好10万+1是11万

但是小姐姐现在报价就是11万卧槽,怎么办,update直接改成12万吧不然没法结婚啊。

重点了来,为了让大加更能了解Lock锁的原理我直接手写一个Lock锁,一样能娶到小姐姐。

我放到下期

 

这是一个关于Java中的升级过程的问题。我会尽力解答,但是请注意我的回答可能会涉及一些技术术语。 Java中的分为四种级别:无、偏向、轻量级和重量级。这些级别是根据竞争的线程数量和状态的不同而定义的。 1. 无:在无状态下,线程可以直接访问共享数据,不需要进行任何同步操作。这种情况只有在并发访问非常低的情况下才会出现,因为在高并发情况下,不同的线程很可能会同时访问同一块数据,这就需要进行同步处理。 2. 偏向:当只有一个线程访问共享数据时,可以使用偏向来提高性能。偏向是一种优化技术,它会记录下最后一个获取的线程,并在下一次访问时直接使用该线程持有的。这样可以减少的竞争,提高程序的性能。当有第二个线程访问同一块数据时,偏向就会升级为轻量级。 3. 轻量级:轻量级是一种比偏向更高级的锁机制。当两个线程访问同一块数据时,偏向就会升级为轻量级。轻量级使用CAS(Compare And Swap)操作来尝试获取,如果成功就直接持有,如果失败就会自旋等待。这种机制能够减少线程的上下文切换,提高程序的性能。当自旋次数超过一定值时,轻量级就会升级为重量级。 4. 重量级:重量级是一种最基本的锁机制。当轻量级自旋次数超过一定值时,就会升级为重量级。重量级使用操作系统的互斥量来进行同步操作,这种机制需要进行线程的上下文切换,会降低程序的性能。 以上就是Java中的升级过程。在实际应用中,应该根据具体的情况选择不同的锁机制,以达到最优的性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值