【Java并发编程九】同步控制

news/2024/11/15 6:07:21/

ReentrantLock(重入锁)

ReentrantLock的基本使用

 ReentrantLock可以自己决定加锁的位置和解锁的位置。

package myTest;import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;public class myTest implements Runnable{// 重入锁public static ReentrantLock lock = new ReentrantLock();public static int i;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new myTest(), "Thread1");Thread t2 = new Thread(new myTest(), "Thread2");t1.start();t2.start();t1.join();t2.join();System.out.println(i);}@Overridepublic void run() {lock.lock();for (int j = 0; j < 10000; j++) {lock.lock();try {i ++;} finally {lock.unlock();}}lock.unlock();System.out.println(Thread.currentThread().getName());}
}
/**
Thread1
Thread2
20000
输出的结果总是上述形式。这是因为Thread1有一个锁是执行完所有循环才会释放。
*/

ReentrantLock.lockInterruptibly() 可中断锁

 如下面代码所示,如果使用ReentrantLock的lock()方法,则会造成死锁。但是使用了lockInterruptibly可中断锁之后,t2在等待2s之后请求另外一个锁没有得到之后,就会不再尝试去获取这个锁,设置中断标志,直接断开。

import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
public class myTest implements Runnable{// 重入锁public static ReentrantLock lock1 = new ReentrantLock();public static ReentrantLock lock2 = new ReentrantLock();int lock;public myTest(int lock) {this.lock = lock;}public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new myTest(1),"Thread1");Thread t2 = new Thread(new myTest(2),"Thread2");t1.start();t2.start();Thread.sleep(2000);t2.interrupt();}@Overridepublic void run() {try {if(lock == 1) {lock1.lockInterruptibly();                System.out.println(Thread.currentThread().getName()+"开始运行");Thread.sleep(500);lock2.lockInterruptibly();} else {lock2.lockInterruptibly();                System.out.println(Thread.currentThread().getName()+"开始运行");Thread.sleep(500);lock1.lockInterruptibly();}} catch (InterruptedException e) {                System.out.println(Thread.currentThread().getName()+"运行出错!");
//                throw new RuntimeException(e);} finally {if(lock1.isHeldByCurrentThread()) {lock1.unlock();}if (lock2.isHeldByCurrentThread()) {lock2.unlock();}            System.out.println(Thread.currentThread().getName()+"退出");}}
}

ReentrantLock.tryLock() 限时等待锁

 使用中断锁虽然可以解决死锁,但是很出现数据不一致的问题。可以使用tryLock() 去等待锁,如果时间到了还没有获得锁,便直接放弃。
 如下面代码所示,执行慢的线程,在等待5s后,会直接执行else里面的代码。

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;public class myTest implements Runnable{// 重入锁public static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new myTest(),"Thread1");Thread t2 = new Thread(new myTest(),"Thread2");t1.start();t2.start();}@Overridepublic void run() {try {if(lock.tryLock(2, TimeUnit.SECONDS)) {Thread.sleep(3000);} else {System.out.println(Thread.currentThread().getName()+"得到锁失败");}} catch (InterruptedException e) {throw new RuntimeException(e);} finally {if(lock.isHeldByCurrentThread()) {System.out.println(Thread.currentThread().getName()+"解锁");lock.unlock();}}}
}

公平锁和非公平锁

 ReentrantLock() 默认是非公平锁,默认值为false,两个线程不会公平的获得锁。
 ReentrantLock(true) 为公平锁,两个线程会公平地获取锁,如下面代码所示,两个线程会依次执行。

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class myTest implements Runnable{// 重入锁public static ReentrantLock lock = new ReentrantLock(true);public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(new myTest(),"Thread1");Thread t2 = new Thread(new myTest(),"Thread2");t1.start();t2.start();}@Overridepublic void run() {while(true) {try {lock.lock();Thread.sleep(1000);System.out.println(Thread.currentThread().getName()+"获得锁");} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock();}}}
}

http://www.ppmy.cn/news/1229963.html

相关文章

Go 语言中的map和内存泄漏

map在内存中总是会增长&#xff1b;它不会收缩。因此&#xff0c;如果map导致了一些内存问题&#xff0c;你可以尝试不同的选项&#xff0c;比如强制 Go 重新创建map或使用指针。 在 Go 中使用map时&#xff0c;我们需要了解map增长和收缩的一些重要特性。让我们深入探讨这一点…

Spring Cloud Stream实践

概述 不同中间件&#xff0c;有各自的使用方法&#xff0c;代码也不一样。 可以使用Spring Cloud Stream解耦&#xff0c;切换中间件时&#xff0c;不需要修改代码。实现方式为使用绑定层&#xff0c;绑定层对生产者和消费者提供统一的编码方式&#xff0c;需要连接不同的中间…

聊聊近些年 CPU 在微架构、IO 速率上的演进过程

大家好&#xff0c;我是飞哥&#xff01; 在上一篇《深入了解 CPU 的型号、代际架构与微架构》 中我们介绍了我手头的一颗 Intel(R) Core(TM) i5 的型号规则&#xff0c;以及它的物理硬件的 Die 图结构。以及它对应的 Skylake 核的微架构实现。 不少同学开始问我其它型号的 CPU…

c++处理tcp粘包问题以及substr方法

c处理tcp粘包问题以及substr方法 1.粘包原因2.tcp基础三次握手四次挥手长连接和和短连接 3.解决方式1.定长消息&#xff1a;2.分隔符消息&#xff1a; 4.substr方法 1.粘包原因 在TCP通信中&#xff0c;粘包是指发送方在发送数据时&#xff0c;多个小的数据包被合并成一个大的…

UDP网络套接字编程

先来说说数据在网络上的传输过程吧&#xff0c;我们知道系统其实终究是根据冯诺依曼来构成的&#xff0c;而网络数据是怎么发的呢&#xff1f; 其实很简单&#xff0c;网络有五层。如下&#xff1a; 如上图&#xff0c;我们知道的是&#xff0c;每层对应的操作系统中的那些地方…

Redis-核心数据结构

五种数据结构 String结构 String结构应用场景 Hash结构 Hash结构应用场景 List结构 List结构应用场景 Set结构 Set结构应用场景 ZSet有序结构 ZSet有序结构应用场景

深兰科技成功入选《2023年度国家知识产权优势企业名单》

2023年11月13日&#xff0c;国家知识产权局正式公布了《2023年度国家知识产权优势企业的名单》(以下简称“《名单》”)。深兰人工智能科技(上海)股份有限公司成功入选&#xff0c;荣获“国家知识产权优势企业”称号。 “国家知识产权优势企业”是指企业经营范围属于国家重点发展…

leetcode:反转链表

题目描述 题目链接&#xff1a;206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; 分析题目 思路一 我们可以设计算法让整个链表掉头 定义三个代码n1,n2,n3 n1指向NULL&#xff0c;n2指向head&#xff0c;n3指向第二个结点 当n2不为NULL的时候&#xff0c;让n2->ne…