多线程-锁的分类-1.自旋锁

锁的公共父类接口

/**
 * Created by zongx on 2019/10/9.
 */
public interface ThreadLock {
    public void lock();
    public void unlock();
}

自旋和阻塞的区别:

自旋——线程反复检查锁变量是否可用。无线程上下文切换

阻塞——让处理器去执行其他的可执行的线程。有线程上下文切换

自旋锁通过Atomic的CAS实现

1.1 浅析CompareAndSet(CAS):

AtomicInteger类compareAndSet通过原子操作实现了CAS操作,最底层基于汇编语言实现。
CAS是Compare And Set的一个简称,如下理解:
  1,已知当前内存里面的值current和预期要修改成的值new传入
  2,内存中AtomicInteger对象地址对应的真实值(因为有可能别修改)real与current对比,
       相等表示real未被修改过,是“安全”的,将new赋给real结束然后返回;不相等说明real已经被修改,结束并重新执行1直到修改成功

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

重点看一下valueoffset

    private static final long valueOffset;
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

 

在生成一个AtomicInteger对象后,可以看做生成了一段内存,对象中各个字段按一定顺序放在这段内存中,字段可能不是连续放置的,

unsafe.objectFieldOffset(Field f)这个方法准确地告诉我"value"字段相对于AtomicInteger对象的起始内存地址的字节相对偏移量。

    private volatile int value;
 
    /**
     * Creates a new AtomicInteger with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
 
    /**
     * Creates a new AtomicInteger with initial value {@code 0}.
     */
    public AtomicInteger() {
    }

 value是一个volatile变量,不同线程对这个变量进行操作时具有可见性,修改与写入操作都会存入主存中,并通知其他cpu中该变量缓存行无效,保证了每次读取都是最新的值

/**
 * Atomically update Java variable to <tt>x</tt> if it is currently
 * holding <tt>expected</tt>.
 * @return <tt>true</tt> if successful
 */
public final native boolean compareAndSwapInt(Object o, long offset,int expected,int x);

总的来说,Atomic实现了高效无锁(底层还是用到排它锁(native方法),不过底层处理比java层处理要快很多)与线程安全(volatile变量特性),CAS一般适用于计数;多线程编程也适用,多个线程执行AtomicXXX类下面的方法,当某个线程执行的时候具有排他性,在执行方法中不会被打断,直至当前线程完成才会执行其他的线程。

1.2 代码实现

package lock.spinlock;

import lock.ThreadLock;

import java.util.concurrent.atomic.AtomicReference;

/**
 * Created by zongx on 2019/10/8.
 * 自旋锁
 * AtomicInteger类compareAndSet通过原子操作实现了CAS操作,最底层基于汇编语言实现。
 * CAS是Compare And Set的一个简称,如下理解:
 *  1,已知当前内存里面的值current和预期要修改成的值new传入
 *  2,内存中AtomicInteger对象地址对应的真实值(因为有可能别修改)real与current对比,
 *     相等表示real未被修改过,是“安全”的,将new赋给real结束然后返回;不相等说明real已经被修改,结束并重新执行1直到修改成功
 *
 */

public class SpinLock implements ThreadLock {
    private AtomicReference<Thread> cas = new AtomicReference<Thread>();//进行自选的主体

    public void lock() {
        Thread currentThread = Thread.currentThread();//锁的关键部位,通过对当前线程的CAS进行操作
        //实际值,初始是null
        while(!cas.compareAndSet(null,currentThread)){

        }
    }

    public void unlock() {
        Thread currentThread = Thread.currentThread();//锁的关键部位,通过对当前线程的CAS进行操作
        cas.compareAndSet(currentThread,null);
    }
}
//线程类与Demo类
package lock.spinlock;

import lock.ThreadLock;

import java.util.Random;

/**
 * Created by zongx on 2019/9/20.
 */
public class MyThread extends Thread {

    private ThreadLock lock;

    public MyThread(String name , ThreadLock lock) {
        super(name);
        this.lock = lock;
    }

    @Override
    public void run() {
        lock.lock();
        for (int i = 0; i < 3; i++) {
            try {
                Random random = new Random();
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "当前线程运行次数" + i);
        }
        lock.unlock();
    }
}


package lock.spinlock;

/**
 * Created by zongx on 2019/10/8.
 */
public class Demo {

    public static void main(String[] args) {
        SpinLock spinLock = new SpinLock();
        MyThread thread1 = new MyThread("Thread1", spinLock);
        MyThread thread2 = new MyThread("Thread2", spinLock);
        MyThread thread3 = new MyThread("Thread3", spinLock);

        thread1.start();
        thread2.start();
        thread3.start();

    }
}

运行结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值