互斥锁(Mutex,mutual exclusion)

概念

互斥锁(Mutex,mutual exclusion的缩写 )是一种用于实现临界区保护的同步原语,目的是确保在任意时刻,只有一个线程或进程能够访问特定的共享资源,防止数据竞争和不一致性 。临界区是程序中访问共享资源的代码片段,线程在进入临界区前获取互斥锁,退出时释放锁,以此保证同一时间只有一个线程能执行该代码段。

操作

  • 锁定(Lock):线程进入临界区前尝试获取互斥锁。若锁已被其他线程持有,当前线程将被阻塞,直到锁可用。
  • 解锁(Unlock):线程退出临界区后释放持有的互斥锁,使其他等待线程可获取该锁。

实现方式

  • 硬件实现
    • 在单处理器系统中,可通过关闭中断防止上下文切换,确保临界区操作的原子性,但此方法不适用于多处理器系统。
    • 在多处理器环境下,常利用原子操作,如测试并设置(Test - and - Set)或比较并交换(Compare - and - Swap)实现互斥锁。这些操作由硬件支持,能在一个原子操作中完成锁状态的检查和设置。
  • 软件实现:缺乏硬件支持时,可使用软件算法实现互斥锁,如Dekker算法和Peterson算法 。但这些算法需频繁检查共享变量状态,可能导致忙等待,浪费CPU资源。

使用注意事项

  • 死锁:多个线程若以不同顺序获取多个锁,可能导致死锁。比如线程A持有锁1等待锁2,线程B持有锁2等待锁1,双方都无法继续执行。避免死锁可确保所有线程按相同顺序获取锁,或采用尝试锁定机制,无法获取锁时采取适当措施。
  • 优先级反转:高优先级线程等待低优先级线程释放锁,会使系统性能下降。可使用优先级继承协议,让低优先级线程持有锁时临时提升优先级。
  • 锁的粒度:锁粒度过大降低系统并发性能,粒度过小则增加锁管理开销,需依具体情况选择合适粒度。

Java代码示例

在Java中,可通过java.util.concurrent.locks.ReentrantLock类实现互斥锁功能,示例如下:

import java.util.concurrent.locks.ReentrantLock;

class SharedResource {
    private int count = 0;
    private ReentrantLock lock = new ReentrantLock();

    public void increment() {
        lock.lock(); // 加锁
        try {
            count++;
        } finally {
            lock.unlock(); // 解锁
        }
    }

    public int getCount() {
        return count;
    }
}

class MyThread extends Thread {
    private SharedResource sharedResource;

    MyThread(SharedResource sharedResource) {
        this.sharedResource = sharedResource;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            sharedResource.increment();
        }
    }
}

public class MutexExample {
    public static void main(String[] args) throws InterruptedException {
        SharedResource sharedResource = new SharedResource();
        MyThread thread1 = new MyThread(sharedResource);
        MyThread thread2 = new MyThread(sharedResource);

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

        thread1.join();
        thread2.join();

        System.out.println("Final count: " + sharedResource.getCount());
    }
}

上述代码中,ReentrantLock实现互斥锁。SharedResource类有共享变量countincrement方法中先调用lock.lock()加锁,确保同一时刻只有一个线程能执行count++操作,操作完成后在finally块中用lock.unlock()解锁,保证锁一定能被释放。MyThread类的线程对共享资源进行操作,main方法创建两个线程并启动,最后输出共享变量最终值。

#牛客创作赏金赛##诺瓦星云求职进展汇总##打工人的工作餐日常##你想吐槽公司的哪些规定##软开人,说说你的烦心事#
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务