Java web项目创建笔记29 之《利用CAS手写一把锁》

1、CAS无锁机制原理(无锁指不是竞争去抢)
1)定义一个锁的状态
2)状态值=0,则表示没有线程获取到该锁
3)状态值=1,则表示有线程已经持有该锁
实现细节:
2、CAS获取锁的流程:
将该锁的状态从0改为1
能够修改成功,则表示获取锁成功
如果获取锁失败,则不会阻塞而是通过循环(自旋来控制重试)
3、CAS释放锁的流程:
将该锁的状态从1改为0
如果能够修改成功,则表示释放锁成功
4、如果一直获取锁失败,一直在做自旋,非常消耗cpu资源
所以要给它做个次数限制,最多自旋10次
5、在包com.study.base.util下,添加AtomicTryLock.java

package com.study.base.util;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

/**
 * 利用cas手写一把锁
 * 
 * @author User
 *
 */
public class AtomicTryLock {

	/**
	 * 0--表示没有人获取该锁 1--表示该锁已经被线程持有了
	 */
	private AtomicInteger cas = new AtomicInteger(0);

	/**
	 * 记录这把锁当前是被哪个线程所持有的
	 */
	private Thread lockCurrentThread;

	/**
	 * 计数器实现可重入功能
	 */
	private int count;

	/**
	 * 获取锁
	 * 获取成功返回true,cas从0变为1,获取失败返回false,cas更新失败
	 * 
	 * @return
	 */
	public boolean tryLock() {
		boolean result;

		// 如果当前线程已经获取到了锁,线程数增加一,然后返回
		if (lockCurrentThread == Thread.currentThread()) {
			count++;
			return true;
		}

		// 通过自旋不断重试
		while (true) {
			result = cas.compareAndSet(0, 1);
			if (result) {
				lockCurrentThread = Thread.currentThread();
				return result;
			}else {
				System.out.println(Thread.currentThread().getName() + ", 重试");
			}
			//释放cpu资源,避免cpu飙高
//			try {
//				Thread.sleep(1);
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
		}
	}

	/**
	 * 释放锁
	 * 
	 * @return
	 */
	public boolean unLock() {
		// 锁必须要当前拿到锁的线程来释放
		if (lockCurrentThread != Thread.currentThread()) {
			return false;
		}

		if (count > 0) {// 如果大于0,表示当前线程多次获取了该锁,释放锁通过count减一来模拟
			count--;
			return true;
		} else {
			return cas.compareAndSet(1, 0);
		}
	}

	public static void main(String[] args) {
		AtomicTryLock atomicTryLock = new AtomicTryLock();
		IntStream.range(1, 10).forEach((i) -> new Thread(() -> {
			try {
				boolean result = atomicTryLock.tryLock();
				if (result) {
					atomicTryLock.lockCurrentThread = Thread.currentThread();
					System.out.println(Thread.currentThread().getName() + ",获取锁成功!");
				} else {
					System.out.println(Thread.currentThread().getName() + ",获取锁失败!");
				}

			} catch (Exception e) {

			} finally {
				if (atomicTryLock != null) {
					Boolean b = atomicTryLock.unLock();
					if (b) {
						System.out.println(Thread.currentThread().getName() + ",释放锁成功!");
					}
				}
			}
		}).start());
	}

}

6、执行结果

Thread-0,获取锁成功!
Thread-6, 重试
Thread-6, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-4, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-2, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-3, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-0,释放锁成功!
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-6, 重试
Thread-6, 重试
Thread-6, 重试
Thread-6, 重试
Thread-6, 重试
Thread-8,获取锁成功!
Thread-8,释放锁成功!
Thread-6, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-5, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-1, 重试
Thread-2, 重试
Thread-1, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-2, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-4, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-3, 重试
Thread-5, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-7, 重试
Thread-6,获取锁成功!
Thread-6,释放锁成功!
Thread-7, 重试
Thread-7,获取锁成功!
Thread-7,释放锁成功!
Thread-5, 重试
Thread-5,获取锁成功!
Thread-5,释放锁成功!
Thread-3, 重试
Thread-3,获取锁成功!
Thread-3,释放锁成功!
Thread-4, 重试
Thread-4,获取锁成功!
Thread-4,释放锁成功!
Thread-2, 重试
Thread-2,获取锁成功!
Thread-2,释放锁成功!
Thread-1, 重试
Thread-1,获取锁成功!
Thread-1,释放锁成功!

可以看到同一时间只有一个线程获取锁。

参考资料:
https://blog.csdn.net/fuyuwei2015/article/details/83387536

注:最新代码上传至https://github.com/csj50/webapp2.git
 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值