首页 > 编程语言 >Java并发编程中的锁机制详解

Java并发编程中的锁机制详解

时间:2024-07-14 15:40:30浏览次数:13  
标签:count Java Thread lock 编程 详解 demo new public

Java并发编程中的锁机制详解

大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

在Java并发编程中,锁机制是保证线程安全的重要手段。锁的作用是确保同一时刻只有一个线程能够访问被锁保护的资源,从而避免数据不一致和并发冲突。本文将详细介绍Java并发编程中的锁机制,包括内置锁、重入锁、读写锁等,并通过代码示例讲解其使用方法和原理。

1. 内置锁(synchronized)

Java的内置锁是通过synchronized关键字实现的,synchronized可以用来修饰方法或者代码块,确保同一时刻只有一个线程能够执行被synchronized保护的代码。

package cn.juwatech.lock;

public class SynchronizedDemo {
    private int count = 0;

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

    public int getCount() {
        return count;
    }

    public static void main(String[] args) throws InterruptedException {
        SynchronizedDemo demo = new SynchronizedDemo();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                demo.increment();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

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

在上述代码中,increment方法被synchronized修饰,保证了count变量的自增操作是线程安全的。

2. 重入锁(ReentrantLock)

ReentrantLock是Java并发包中的可重入锁,它提供了比synchronized更灵活的锁机制。例如,ReentrantLock可以实现公平锁、非阻塞地获取锁等功能。

package cn.juwatech.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

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

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

    public int getCount() {
        return count;
    }

    public static void main(String[] args) throws InterruptedException {
        ReentrantLockDemo demo = new ReentrantLockDemo();

        Runnable task = () -> {
            for (int i = 0; i < 1000; i++) {
                demo.increment();
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();

        t1.join();
        t2.join();

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

上述代码中,increment方法使用ReentrantLock进行加锁和解锁,确保count变量的自增操作是线程安全的。

3. 读写锁(ReadWriteLock)

ReadWriteLock是另一种常用的锁机制,它允许多个读线程并发地访问,但写线程是独占的。这在读多写少的场景中可以显著提高并发性能。

package cn.juwatech.lock;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

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

    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();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReadWriteLockDemo demo = new ReadWriteLockDemo();

        Runnable writeTask = () -> {
            for (int i = 0; i < 1000; i++) {
                demo.increment();
            }
        };

        Runnable readTask = () -> {
            for (int i = 0; i < 1000; i++) {
                System.out.println("Count: " + demo.getCount());
            }
        };

        Thread t1 = new Thread(writeTask);
        Thread t2 = new Thread(readTask);
        Thread t3 = new Thread(readTask);

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();

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

在上述代码中,increment方法使用写锁进行加锁,getCount方法使用读锁进行加锁,确保读写操作的线程安全。

4. 锁的条件变量

ReentrantLock还提供了条件变量(Condition),可以实现更复杂的线程同步控制。通过Condition对象,可以让线程在某个条件下等待,直到条件满足后再继续执行。

package cn.juwatech.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionDemo {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private boolean ready = false;

    public void waitForCondition() {
        lock.lock();
        try {
            while (!ready) {
                condition.await();
            }
            System.out.println("Condition met, proceeding...");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }

    public void signalCondition() {
        lock.lock();
        try {
            ready = true;
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ConditionDemo demo = new ConditionDemo();

        Runnable waitingTask = demo::waitForCondition;
        Runnable signalingTask = demo::signalCondition;

        Thread t1 = new Thread(waitingTask);
        Thread t2 = new Thread(signalingTask);

        t1.start();
        Thread.sleep(1000);
        t2.start();

        t1.join();
        t2.join();
    }
}

在上述代码中,waitForCondition方法在条件不满足时等待,直到signalCondition方法将条件置为满足并通知所有等待线程。

5. StampedLock

StampedLock是Java 8引入的一种锁机制,它提供了更高效的读写锁,并且支持乐观读操作。StampedLock的主要特点是它使用了戳记(stamp)来控制锁的状态。

package cn.juwatech.lock;

import java.util.concurrent.locks.StampedLock;

public class StampedLockDemo {
    private int count = 0;
    private final StampedLock stampedLock = new StampedLock();

    public void increment() {
        long stamp = stampedLock.writeLock();
        try {
            count++;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
    }

    public int getCount() {
        long stamp = stampedLock.tryOptimisticRead();
        int currentCount = count;
        if (!stampedLock.validate(stamp)) {
            stamp = stampedLock.readLock();
            try {
                currentCount = count;
            } finally {
                stampedLock.unlockRead(stamp);
            }
        }
        return currentCount;
    }

    public static void main(String[] args) throws InterruptedException {
        StampedLockDemo demo = new StampedLockDemo();

        Runnable writeTask = () -> {
            for (int i = 0; i < 1000; i++) {
                demo.increment();
            }
        };

        Runnable readTask = () -> {
            for (int i = 0; i < 1000; i++) {
                System.out.println("Count: " + demo.getCount());
            }
        };

        Thread t1 = new Thread(writeTask);
        Thread t2 = new Thread(readTask);
        Thread t3 = new Thread(readTask);

        t1.start();
        t2.start();
        t3.start();

        t1.join();
        t2.join();
        t3.join();

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

在上述代码中,increment方法使用写锁进行加锁,getCount方法尝试使用乐观读锁,如果失败则降级为悲观读锁,确保读写操作的线程安全。

总结

本文详细介绍了Java并发编程中的锁机制,包括内置锁、重入锁、读写锁、条件变量和StampedLock。通过这些示例代码,开发者可以更好地理解和使用Java的各种锁机制,提高并发程序的性能和可靠性。

著作权归聚娃科技微赚淘客系统开发者团队,转载请注明出处!

标签:count,Java,Thread,lock,编程,详解,demo,new,public
From: https://www.cnblogs.com/szk123456/p/18301639

相关文章

  • Cuda编程:__syncthreads运行时API在访问共享内存时的使用
    该运行时API的作用作为在访问共享内存时作为线程块内的同步机制出现,保证同一线程块内所有线程到程序运行到这个运行时API调用时都能运行完毕(注意,该API不能同步不同线程块内的线程),例如下列Cuda静态共享内存使用代码示例程序中的第23行所示:/*************************************......
  • 高质量C/C++编程指南总结(四)—— 表达式和基本语句
    1.运算符优先级如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。 2.复合表达式不要编写太复杂的复合表达式。不要有多用途的复合表达式。不要把程序中的复合表达式与“真正的数学表达式”混淆。 3.if语句不可将布尔变量直接与 ......
  • 函数式编程的交响曲:探索LangChain对函数式编程特性的支持
    函数式编程的交响曲:探索LangChain对函数式编程特性的支持引言在现代软件开发中,函数式编程(FunctionalProgramming,FP)以其独特的优势,如无副作用、易于并行处理等,逐渐受到开发者的青睐。LangChain作为一个多语言编程工具链,其设计理念在于支持多种编程范式,包括函数式编程。......
  • 高质量C/C++编程指南总结(三)—— 命名规则
    标识符应当直观,可望文知义。标识符的长度应当符合“min-length&& max-information”原则。命名规则尽量与所采用的操作系统或开发工具的风格保持一致。程序中不要仅靠大小写区分相似的标识符。程序中不要出现标识符完全相同的局部变量和全局变量。变量的名字应当使用“......
  • 细粒度掌控:精通Gradle中Java插件的配置艺术
    细粒度掌控:精通Gradle中Java插件的配置艺术引言Gradle是一个灵活且功能丰富的构建工具,它通过插件扩展其功能。Java插件是Gradle中最常用的插件之一,为Java项目提供了丰富的构建生命周期任务和约定。合理配置Java插件,可以极大提升Java项目的构建效率和质量。Java插件简介G......
  • JAVA入门到精通:第一课
    一、JDK下载1、访问oracle官网,选择Java建议选择Java17(长期支持版本)2、选择合适的安装包3、安装过程:傻瓜式“下一步”安装安装路径:建议创建一个新的文件夹,在D盘统一管理4、安装完成后,路径中的文件目录如下所示bin:是最重要的文件夹二、HelloWord程序编写1、记事本......
  • Java基础(For循环/While循环/一维数组/二维数组)
    for循环语句for循环语句中两个分号是绝对不能少的,其他不可以没有,此时for循环就成了死循环。publicclassForDemo{ publicstaticvoidmain(String[]args) { //死循环 for(;;) { System.out.println("for---"); } }}while循环语句格式:初始......
  • Java零基础-集合:集合框架中的工具类
    哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的......
  • 记录些Java题集(1)
    接口防刷机制接口被刷指的是同一接口被频繁调用,可能是由于以下原因导致:恶意攻击:攻击者利用自动化脚本或工具对接口进行大量请求,以消耗系统资源、拖慢系统响应速度或达到其他恶意目的。误操作或程序错误:某些情况下,程序错误或误操作可能导致接口被重复调用,例如循环调用或者定时......
  • 详解tcp四次挥手
    TCP四次挥手详解TCP四次挥手用于关闭客户端和服务器之间的连接。它确保双方能够有序地终止连接,避免数据丢失。四次挥手的过程第一次挥手:客户端发送FIN报文客户端向服务器发送一个FIN(Finish)报文,请求终止连接。报文包含一个序列号,如FIN=1,seq=x。意义:客户端通知服务......