多线程与高并发cas问题

多线程与高并发3

CAS

cas(期望值,更新值)

eg:m++的操作

m=0 m++

cas(0,1){

​ for循环自旋 当V == m的当前值0(由操作系统源语保证的不会v==m)

​ m++

}

其实无所的操作的原理是乐观锁

对比测试sync Long、AtomicLong、LongAdder 三种count++的方式的速度

package com.zkj.mca.LockTuning;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * @Author: zhaokj
 * @Date: 2022/08/31/22:13
 * @Description: 测试sync Long、AtomicLong、LongAdder 三种count++的方式的速度
 **/
public class AtomicVsSyncVsLongAdder {
    static Long count2 = 0L;
    static AtomicLong count1 = new AtomicLong(0);
    static LongAdder count3 = new LongAdder();

    public static void main(String[] args) throws InterruptedException {
        //创建1000个线程
        Thread[] threads = new Thread[1000];
        System.out.println("-------------------------------------------atomic------------------------------------------------");
        for (int i = 0; i<threads.length; i++){
            threads[i] =
                    new Thread(()->{
                        //1000个线程对count1进行累加直到100000
                        for (int k=0;k<100000;k++) count1.incrementAndGet();
                    });
        }
        long start = System.currentTimeMillis();
        for (Thread t: threads) t.start();
        for (Thread t: threads) t.join();
        long end = System.currentTimeMillis();
        TimeUnit.SECONDS.sleep(10);
        System.out.println("Atomic: " + count1.get() + "   time"+(end-start));
        //----------------------------------------------------------------------
        System.out.println("-------------------------------------------sync------------------------------------------------");
        Object o = new Object();
        for (int i = 0; i<threads.length; i++){
            threads[i] =
                    new Thread(()->{
                        //1000个线程对count1进行累加直到100000
                        for (int k=0;k<100000;k++)
                            synchronized (o){
                                count2++;
                            }
                    });
        }
        start = System.currentTimeMillis();
        for (Thread t: threads) t.start();
        for (Thread t: threads) t.join();
        end = System.currentTimeMillis();
        TimeUnit.SECONDS.sleep(10);
        System.out.println("synv: " + count1.get() + "   time"+(end-start));
        //---------------------------------------------------------------------------
        System.out.println("-------------------------------------------LongAdder------------------------------------------------");
        for (int i = 0; i<threads.length; i++){
            threads[i] =
                    new Thread(()->{
                        //1000个线程对count1进行累加直到100000
                        for (int k=0;k<100000;k++) count3.increment();
                    });
        }
        start = System.currentTimeMillis();
        for (Thread t: threads) t.start();
        for (Thread t: threads) t.join();
        end = System.currentTimeMillis();
        TimeUnit.SECONDS.sleep(10);
        System.out.println("LongAdder: " + count1.get() + "   time"+(end-start));
    }
}

多线程与高并发cas问题_第1张图片

在多线程的情况下LongAdder速度高于Atomic高于Sync,原因是sync使用了锁,有可能锁会升级为重粒度的锁,Atomic的原理是CAS,longadder的原理是分段锁,他的核心也是CAS实现的

LongAdder

多线程与高并发cas问题_第2张图片

Atomic

package com.zkj.mca.LockTuning;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * @Author: zhaokj
 * @Date: 2022/08/31/22:13
 * @Description: 测试sync Long、AtomicLong、LongAdder 三种count++的方式的速度
 **/
public class AtomicVsSyncVsLongAdder {
    static Long count2 = 0L;
    static AtomicLong count1 = new AtomicLong(0);
    static LongAdder count3 = new LongAdder();

    public static void main(String[] args) throws InterruptedException {
        //创建1000个线程
        Thread[] threads = new Thread[1000];
        for (int i = 0; i<threads.length; i++){
            threads[i] =
                    new Thread(()->{
                        //1000个线程对count1进行累加直到100000
                        for (int k=0;k<100000;k++) count1.incrementAndGet();
                    });
        }
        long start = System.currentTimeMillis();
        for (Thread t: threads) t.start();
        for (Thread t: threads) t.join();
        long end = System.currentTimeMillis();
        TimeUnit.SECONDS.sleep(10);
        System.out.println("Atomic: " + count1.get() + "   time"+(end-start));

    }
}

多线程与高并发cas问题_第3张图片

可重入锁

sync就是锁定的一个对象,是对一个对象的头部两位进行了加锁的操作,如果说锁了一次之后线程又重新的执行回来发现锁的对象就是自己的话可以再次加锁执行自己的代码

不同线程:

package com.zkj.mca.LockTuning.ReentrantLock;

import java.util.concurrent.TimeUnit;

/**
 * @Author: zhaokj
 * @Date: 2022/09/23/22:21
 * @Description:sync一定是可重入锁,否则不能满足子类调用父类的方法
 * 两个线程竞争同一个资源(锁)m2的线程无法获得锁
 *
 **/
public class ReentrantLock1 {
    synchronized void m1(){
        for (int i = 0;i<10;i++){
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
    }
    synchronized void m2(){
        System.out.println("m2-----------------");
    }

    public static void main(String[] args) {
        ReentrantLock1 reentrantLock1 = new ReentrantLock1();
        new Thread(reentrantLock1::m1).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(reentrantLock1::m2).start();

    }
}

同一线程

package com.zkj.mca.LockTuning.ReentrantLock;

import java.util.concurrent.TimeUnit;

/**
 * @Author: zhaokj
 * @Date: 2022/09/23/22:21
 * @Description:sync一定是可重入锁,否则不能满足子类调用父类的方法
 * 两个线程竞争同一个资源(锁)m2的线程无法获得锁
 *
 **/
public class ReentrantLock1 {
    synchronized void m1(){
        for (int i = 0;i<10;i++){
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
            if (i == 2){
                System.out.println("从同一线程调用m2");
                m2();
            }

        }
    }
    synchronized void m2(){
        System.out.println("m2-----------------");
    }

    public static void main(String[] args) {
        ReentrantLock1 reentrantLock1 = new ReentrantLock1();
        new Thread(reentrantLock1::m1).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(reentrantLock1::m2).start();

    }
}

多线程与高并发cas问题_第4张图片

ReentrantLock

ReentrantLock和sync的区别

1.tryLock

package com.zkj.mca.LockTuning.ReentrantLock;

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

/**
 * @Author: zhaokj
 * @Date: 2022/09/27/20:53
 * @Description:ReentrantLock 可以替代sync,但是需要手动解锁
 **/
public class ReentrantLock2 {
    Lock lock = new ReentrantLock();
    void m1(){
        try {
            lock.lock();
            for (int i = 0;i<10;i++){
                TimeUnit.SECONDS.sleep(1);
                System.out.println(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    void m2(){
        boolean locked = false;
        try {
            locked = lock.tryLock(5,TimeUnit.SECONDS);
            System.out.println("m2----"+locked);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (locked) lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLock2 reentrantLock2 = new ReentrantLock2();
        new Thread(reentrantLock2::m1).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(reentrantLock2::m2).start(); 
    }
}

现在显然10s>5s无法拿到锁

![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VOpY2hMl-1678278197477)(…/Library/Application Support/typora-user-images/image-20221101223246712.png)](https://img-blog.csdnimg.cn/1376a67d0b644aa2913cb605ba5f30a5.png)

package com.zkj.mca.LockTuning.ReentrantLock;

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

/**
 * @Author: zhaokj
 * @Date: 2022/09/27/20:53
 * @Description:ReentrantLock 可以替代sync,但是需要手动解锁
 **/
public class ReentrantLock2 {
    Lock lock = new ReentrantLock();
    void m1(){
        try {
            lock.lock();
            for (int i = 0;i<20;i++){
                TimeUnit.SECONDS.sleep(1);
                System.out.println(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    void m2(){
        boolean locked = false;
        try {
            locked = lock.tryLock(5,TimeUnit.SECONDS);
            System.out.println("m2----"+locked);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (locked) lock.unlock();
        }
    }

    public static void main(String[] args) {
        ReentrantLock2 reentrantLock2 = new ReentrantLock2();
        new Thread(reentrantLock2::m1).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(reentrantLock2::m2).start();
    }
}

2s<5s 就可以得到锁

多线程与高并发cas问题_第5张图片

你可能感兴趣的:(Java基础,java,jvm,算法)