首先是简单的自旋锁代码实现:
package org.cc.concur; public class MyLock { public MyLock() { } private boolean isLocked=false; public synchronized void lock() throws InterruptedException{ while(isLocked){ System.out.println(Thread.currentThread().getName()+"堵塞了"); wait(); } isLocked=true; System.out.println(Thread.currentThread().getName()+"正在运行"); Thread.currentThread().sleep(1000); } public synchronized void unlock(){ isLocked=false; notifyAll(); } }
这是一个最简单的自旋锁
有如下特点:
- 不支持重入
- 任一非锁定线程执行unlock都会导致锁失效(这个是操作相关的)
以上的特点用如下代码来测试:
// 正常使用情况
public void testLock() throws InterruptedException{ final MyLock lock=new MyLock(); Thread thread=new Thread(new Runnable(){ @Override public void run(){ try{ lock.lock(); System.out.println("-------1线程正在运行"); Thread.sleep(1000); System.out.println("-------1线程运行结束。。。。。。"); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } }, "线程2"); thread.start(); lock.lock(); System.out.println("-------主线程正在运行"); Thread.sleep(1000); System.out.println("-------主线程运行结束。。。。。。"); lock.unlock(); }
输出:
main正在运行 -------主线程正在运行 线程1堵塞了 -------主线程运行结束。。。。。。 线程1正在运行
// 非锁定线程使用了unlock
Thread thread=new Thread(new Runnable(){ @Override public void run(){ try{ lock.unlock(); lock.lock(); System.out.println("-------1线程正在运行"); Thread.sleep(1000); System.out.println("-------1线程运行结束。。。。。。"); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } }, "线程1");
这样可以看出 任何的非锁定线程的线程都可以解开锁
main正在运行 -------主线程正在运行 线程1正在运行 -------主线程运行结束。。。。。。 -------1线程正在运行
最后一种就是重入的情况:
lock.lock(); lock.lock(); System.out.println("-------主线程正在运行"); Thread.sleep(1000); System.out.println("-------主线程运行结束。。。。。。"); lock.unlock();
输出:
main正在运行 main堵塞了 线程1堵塞了
以上的地方改进很简单
设置一个属性保存进入的线程对象 并进行一些判断
以上一些缺点共同写入了代码:
package org.cc.concur; public class MyLockReentranceLock { public MyLockReentranceLock() { } private boolean isLocked=false; private int count=0; private Object currentThread=null; public synchronized void lock() throws InterruptedException{ while(isLocked&&Thread.currentThread()!=currentThread){ System.out.println(Thread.currentThread().getName()+"堵塞了"); wait(); } currentThread=Thread.currentThread(); if(count==0){ isLocked=true; } count++; System.out.println(Thread.currentThread().getName()+"正在运行"); Thread.sleep(1000); } public synchronized void unlock(){ if(Thread.currentThread()==currentThread){ count--; System.out.println("---状态:"+Thread.currentThread().getName()+": "+count); } if(count==0){ isLocked=false; currentThread=null; System.out.println(Thread.currentThread().getName()+"-----解放了锁"); notifyAll(); } } public static void main(String []args) throws InterruptedException{ final MyLockReentranceLock lock=new MyLockReentranceLock(); // 支持重入 Thread thread=new Thread(new Runnable(){ @Override public void run(){ try{ lock.lock(); System.out.println("-------1线程正在运行"); Thread.sleep(1000); System.out.println("-------1线程运行结束。。。。。。"); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } }, "线程1"); Thread thread2=new Thread(new Runnable(){ @Override public void run(){ try{ lock.unlock(); lock.lock(); System.out.println("-------2线程正在运行"); Thread.sleep(1000); System.out.println("-------2线程运行结束。。。。。。"); }catch(Exception e){ e.printStackTrace(); }finally{ lock.unlock(); } } }, "线程2"); thread2.start(); thread.start(); lock.lock(); lock.lock(); System.out.println("主线程正在运行。。。。。"); Thread.sleep(1000); System.out.println("主线程运行结束。。。。。。"); lock.unlock(); lock.unlock(); } }
一次运行时的情况:
main正在运行 main正在运行 主线程正在运行。。。。。 线程1堵塞了 线程2堵塞了 主线程运行结束。。。。。。 ---状态:main: 1 ---状态:main: 0 main-----解放了锁 线程2正在运行 -------2线程正在运行 线程1堵塞了 -------2线程运行结束。。。。。。 ---状态:线程2: 0 线程2-----解放了锁 线程1正在运行 -------1线程正在运行 -------1线程运行结束。。。。。。 ---状态:线程1: 0 线程1-----解放了锁
相关推荐
"基于SMP的Linux内核自旋锁分析" 本文将对基于SMP(Symmetrical Multi-Processing)的Linux内核自旋锁进行分析。自旋锁是一种常用的并发机制,用于解决多处理器系统中的并发执行问题。在Linux内核中,自旋锁是实现...
### 信号量、互斥体和自旋锁的区别详解 #### 一、基本概念与应用场景 **信号量**、**互斥体**和**自旋锁**是操作系统中三种常用的同步机制,主要用于解决多线程或多进程环境中资源的并发访问问题。这三种机制虽然...
队列锁则提供了更好的可扩展性,适用于更多线程的情况。 总的来说,无锁编程和自旋锁在高性能并发系统中具有重要意义,它们可以帮助我们构建高效、低延迟的多线程程序。通过学习这些C++实现,我们可以更好地理解和...
在Windows驱动程序开发中,理解和掌握中断请求级别(IRQ)以及自旋锁是至关重要的。本视频教程将深入探讨这两个核心概念,旨在帮助开发者提升驱动程序的性能和稳定性。 首先,我们来了解一下中断请求级别(IRQ)。...
本文将深入探讨两种常见的同步机制——信号量和自旋锁,它们在Linux内核中的应用以及如何有效地使用它们。 #### 一、信号量:睡眠锁机制 **信号量**是一种广泛使用的同步机制,用于控制多个进程对共享资源的访问。...
在单CPU且不可抢占的内核中,自旋锁的操作会简化为无操作,但在多CPU或可抢占的环境中,自旋锁就显得尤为重要。 Linux内核提供了多种自旋锁的API,例如: 1. `spin_lock_init(x)`:初始化自旋锁x。 2. `DEFINE_...
在分析 `spin_lock.c` 示例程序时,我们会看到如何在实际代码中使用这些自旋锁函数,以及如何正确地进行同步操作。通过运行和调试这个程序,我们可以更好地理解自旋锁的工作原理及其在多线程环境中的应用。 总之,...
本文主要讨论了四种锁类型:乐观锁、悲观锁、自旋锁以及Java中的synchronized同步锁,并深入解析了synchronized锁的内部机制,包括其核心组件、实现方式以及锁的状态。 1. **乐观锁**:乐观锁假设在多线程环境下,...
自旋锁争用的症状通常表现为数据库系统响应缓慢,CPU使用率异常高,以及事务执行时间增长。当多个并发进程争夺同一资源时,系统可能会长时间地将CPU时间浪费在等待锁的释放上,而不是进行有效的数据处理。 在自旋锁...
Linux 内核自旋锁死锁检测机制设计与实现 在 Linux 内核中,自旋锁是一种广泛应用的锁机制,可以大幅提高系统性能和吞吐量。但是,自旋锁的使用不当,会立即将系统锁死,直至人工重启才能解锁,这是危害性最大的...
本文将深入探讨Linux系统中基于自旋锁的进程调度实现,以及自旋锁、共享内存和汇编语言在其中的作用。 自旋锁(Spinlock)是一种简单的互斥机制。当一个进程持有一个自旋锁时,其他试图获取该锁的进程将进入“自旋...
深入讲解CAS自旋锁的实现机理和原理 CAS(Compare and Swap)是实现自旋锁或乐观锁的核心操作,它的出现是为了解决原子操作的问题。在多线程环境下,原子操作是保证线程安全的重要手段。CAS操作的实现很简单,就是...
在Golang中,实现分布式自旋锁和本地自旋锁是一种常见的并发控制策略,用于解决多线程或分布式系统中的资源竞争问题。自旋锁的基本思想是,当一个线程试图获取锁时,如果锁已被其他线程持有,它会不断地检查锁的状态...
本文将深入探讨如何使用Redis实现分布式锁,以及如何利用自旋式加锁和Lua脚本实现原子性解锁。 首先,我们来理解分布式锁的基本概念。分布式锁是在多节点之间共享资源时,用于协调各个节点的访问控制机制。在分布式...
- 线程自旋等待的逻辑:如何避免无休止地自旋,以及何时停止自旋尝试获取锁。 - 公平策略的实现:如何保证线程按照请求的顺序获取锁。 - 内存同步原语的使用:如CAS(Compare And Swap)操作,用于无锁编程。 - 锁的...
这些示例可能涵盖了自旋锁的基本使用、在中断处理中的应用以及可能的优化技巧。通过阅读和理解这些源码,开发者可以深入学习自旋锁的工作原理和最佳实践。 总结来说,Linux下的自旋锁是内核同步的重要工具,主要...
自旋锁的设计理念是,在等待锁释放的过程中,持有锁的任务会不断地检查锁的状态,即“自旋”,直到锁变为可用状态。这种方式在锁的持有时间极短的情况下是非常高效的,因为减少了上下文切换的开销。然而,如果锁被长...
java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁
5. **自旋锁优化**:为了防止饥饿和提高效率,Linux内核提供了可剥夺自旋锁(`spin_lock_irqsave()`和`spin_unlock_irqrestore()`)和不可剥夺自旋锁(`spin_lock_bh()`和`spin_unlock_bh()`)。前者会禁用中断,后...