当前位置: 首页 > article >正文

浅谈Java之多线程锁处理

一、基本介绍

        在Java中,多线程环境下的锁处理是一个非常重要的话题,因为它涉及到线程安全和数据一致性。Java提供了多种锁机制来帮助开发者控制对共享资源的访问。

二、锁处理方式

内置锁(synchronized)

  • synchronized关键字可以用来修饰方法或者代码块,确保同一时间只有一个线程可以执行该段代码。
  • 对于方法,它锁定的是调用该方法的对象实例。
  • 对于代码块,它锁定的是括号内指定的对象。
public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

重入锁(ReentrantLock)

  • ReentrantLockjava.util.concurrent.locks包下的一个类,提供了与synchronized关键字类似的同步功能,但是更加灵活。
  • 它支持尝试非阻塞地获取锁、可中断地获取锁、超时获取锁等。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Counter {
    private final Lock lock = new ReentrantLock();
    private int count = 0;

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

读写锁(ReadWriteLock)

  • ReadWriteLock允许多个读操作同时进行,但写操作是独占的。
  • 适用于读操作远多于写操作的场景。
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Counter {
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private int count = 0;

    public void increment() {
        rwLock.writeLock().lock();
        try {
            count++;
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    public int getCount() {
        rwLock.readLock().lock();
        try {
            return count;
        } finally {
            rwLock.readLock().unlock();
        }
    }
}

显式锁(Locks)

  • Java还提供了其他类型的锁,如StampedLock,它是一种乐观锁,提供了一种更细粒度的锁定机制。

条件变量(Condition)

  • 与锁配合使用,用于线程间的协调,允许一个或多个线程等待某些条件成立。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class BoundedBuffer {
    private final Object[] items = new Object[100];
    private int putPtr, takePtr, count;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) {
                notFull.await();
            }
            items[putPtr] = x;
            if (++putPtr == items.length) putPtr = 0;
            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                notEmpty.await();
            }
            Object x = items[takePtr];
            if (++takePtr == items.length) takePtr = 0;
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }
}

原子变量(Atomic Variables)

  • 对于简单的计数器或累加器,可以使用java.util.concurrent.atomic包下的原子变量,如AtomicInteger,它们利用底层硬件的原子指令来保证操作的原子性。
import java.util.concurrent.atomic.AtomicInteger;

public class Counter {
    private final AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();
    }

    public int getCount() {
        return count.get();
    }
}

三、注意事项

  • 锁的粒度:锁的粒度越细,性能越好,但实现起来越复杂。
  • 锁的顺序:避免死锁,确保所有线程获取锁的顺序一致。
  • 锁的持有时间:尽量减少锁持有的时间,以减少等待时间。
  • 锁的公平性:ReentrantLock允许设置公平锁,以确保线程获取锁的顺序。


http://www.kler.cn/a/322867.html

相关文章:

  • 现代密码学|公钥密码体制 | RSA加密算法及其数学基础
  • <websocket><PLC>使用js和html实现webscoket,与PLC进行socket通讯的实例
  • 云速搭助力用友 BIP 平台快速接入阿里云产品
  • 大模型(LLMs)进阶篇
  • 第二十一周机器学习笔记:动手深度学习之——数据操作、数据预处理
  • HbuilderX 插件开发-模板创建
  • kali linux crunch工具使用 -- 生成字典
  • 【常见框架漏洞】ThinkPHP、struts2、Spring、Shiro
  • 【数据结构】堆(Heap)详解
  • 前端框架的选择与考量:一场技术的盛宴
  • [Doc][ROS2]订阅发布、服务客户端区别
  • django drf 自动注册路由
  • Leetcode尊享面试100题-252.会议室
  • 产品推介——SOP4 随机相位可控硅光耦KLM305X
  • Docker Init 实战详解:从入门到精通
  • 前端练习总结(1)
  • 选择、冒泡、插入排序
  • 【Redis 源码】2项目结构说明
  • c语言中的杨氏矩阵的介绍以及元素查找的方法
  • Spring Boot 中实现任务后台处理的几种常见方式
  • 【笔记】自动驾驶预测与决策规划_Part4_时空联合规划
  • 数据结构及基本算法
  • LeetCode 2266. 统计打字方案数
  • UE4_Niagara基础实例—使用自定义模块二
  • DataLight(V1.4.5) 版本更新,新增 Ranger、Solr
  • Sony IMX334LQR-C 1/1.8寸 8.42 M像素