前面 使用自旋锁实现了一把锁,(请看 第5篇)

volatile 三大特性: 可见性, 不保证原子性, 禁止指令重排

为了解决 volatile不保证原子性的问题, 引入了原子类, AtomicInteger, 底层是使用了 CAS 直接变成汇编指令操作硬件,从而解决了 原子性的问题

而 Lock 类的底层实现是 AQS 和CAS,

这里使用 AtomicInteger的特性和自旋锁来实现一把 排队自旋锁 锁:

  class AtomicLock {
private AtomicInteger serviceNum = new AtomicInteger();//等待者
private AtomicInteger ticketNum = new AtomicInteger();//排队号 public int atomicLock() {
// 排队号加1
int myTicketNum = ticketNum.getAndIncrement();
//只要 排队号和 等待着的号不同,等待者就一直循环, 如果相同,就返回排队号, 这里相当于加锁成功
while (serviceNum.get() != myTicketNum) {
}
System.out.println(Thread.currentThread().getName() + "加锁成功");
return myTicketNum;
} public void atomicUnlock(int num) {
// 如果要解锁,就将排队号 +1, 并设置回等待者
int next = num + 1;
serviceNum.compareAndSet(num, next);
System.out.println(Thread.currentThread().getName() + "解锁成功");
} static int num = 0;
public static void main(String[] args) throws InterruptedException {
/**
* 这个锁的缺点是: 如果线程很多, 这么多线程都要操作 同一个Atomicinteger, 且为了保证 各个线程的工作缓存中的数据一致性,
* 会频繁的 在工作缓存和 主存之间进行通信,,造成系统总线和主存之间繁重的流量, 进而降低系统的性能
*
* 但是多处理器系统上,每个进程/线程占用的处理器都在读写同一个变量serviceNum ,每次读写操作都必须在多个处理器缓存之间进行缓存同步,
* 这会导致繁重的系统总线和内存的流量,大大降低系统整体的性能。
* 如何解决: 使用 CLH锁和MCS锁
*/
AtomicLock atomicLock = new AtomicLock();
for (int i = 0; i < 10; i++) {
new Thread(() -> {
int j = atomicLock.atomicLock();
System.out.println(Thread.currentThread().getName() + "操作开始: num: " + num);
for (int k = 0; k < 20; k++) {
num++;
}
System.out.println(Thread.currentThread().getName() + "操作结束: num: " + num);
atomicLock.atomicUnlock(j);
},"线程"+i).start();
} TimeUnit.SECONDS.sleep(3);
System.out.println("最终结果num: "+num);
}
}

运行结果:



CLH锁和 MCS锁, 这个是目前写的比较好的博客

https://www.jianshu.com/p/1b1b44e84394

最新文章

  1. 06.移动先行之谁主沉浮----我的代码我来写(Xaml的优势)
  2. 夺命雷公狗----Git---6---GitHub基本使用
  3. Oracle循环语句
  4. c#使用WebClient登录网站抓取登录后的网页
  5. 【hdu2795】Billboard
  6. UVa 10815 安迪的第一个字典
  7. 图解Android - Zygote, System Server 启动分析
  8. Android通过URL加载网络图片
  9. phpcms 导航栏点击栏目颜色定位方法
  10. 12.Generics
  11. LibLinear(SVM包)使用说明之(一)README
  12. 萝卜家园32位和64位Win7系统Ghost版
  13. 《剑指Offer》面试题-二维数组中的查找
  14. mongo+mongoose+express
  15. python学习之路前端-CSS
  16. ASP.NET WebApi系列
  17. golang 基本数据结构使用
  18. SQL Server 2012使用Offset/Fetch Next实现分页
  19. 【POJ1741】Tree
  20. 17行代码解决微信小程序图片延迟加载

热门文章

  1. Android so加固的简单脱壳
  2. POJ1201基础差分约束
  3. 推荐算法-聚类-K-MEANS
  4. Access denied for user &#39;电脑用户名&#39;@&#39;localhost&#39;
  5. Spring随堂笔记
  6. Java对象内存分布
  7. 记一次 .NET 某医院HIS系统 CPU爆高分析
  8. FFmpeg应用实践之命令查询
  9. python多进程、多线程服务器和客户端的简单实现
  10. 交叉编译参数--build、host和target的区别