java 读锁有什么用_java可重入锁、读写锁、synchronized 和lock有什么区别?用新的lock有什么好处?你挙例说说...

1、原子引用

package com.example.mybaties;

import lombok.AllArgsConstructor;

import lombok.Getter;

import lombok.ToString;

import java.util.concurrent.atomic.AtomicReference;

/**

* @DESCRIPTION 原子引用

* @Author lst

* @Date 2020-03-24 09:00

*/

public class AtomicReferenceDemo {

public static void main(String[] args) {

User z3 = new User("z3",22);

User li4 = new User("li4",25);

AtomicReference atomicReference = new AtomicReference();

atomicReference.set(z3);

System.out.println(atomicReference.compareAndSet(z3,li4)+ "\t " + atomicReference.get().toString());

System.out.println(atomicReference.compareAndSet(z3,li4)+ "\t " + atomicReference.get().toString());//主物理内存已经变成li4

/**

* true User(userName=li4, age=25)

* false User(userName=li4, age=25)

*/

}

}

@Getter

@ToString

@AllArgsConstructor

class User {

String userName;

int age;

}

2、可重入锁

package com.example.mybaties;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/**

* @DESCRIPTION 可重入锁(也叫递归锁)

* 指的是同一线程外层脳数获得锁之后,内层递归数仍然能获取该锁的代吗,在同一个线程在外层方法英取的时候,

* 在进入内层方法会自动获取锁也即是说,线程可以进入一个任何它已经拥有的所同歩的代码块

*

*

* 就是一个典型的可重入锁

*

* 11invoked sendSms

* 11#######invoked sendEmail

* 12invoked sendSms

* 12#######invoked sendEmail

*

*

*

* @Author lst

* @Date 2020-03-23 14:48

*/

class Phone implements Runnable{

public synchronized void sendSms(){

System.out.println(Thread.currentThread().getId() + "invoked sendSms ");

sendEmail();

}

public synchronized void sendEmail(){

System.out.println(Thread.currentThread().getId() + "#######invoked sendEmail ");

}

Lock lock = new ReentrantLock();//默认非公平锁

@Override

public void run() {

get();

}

public void get(){

lock.lock();

lock.lock();

System.out.println(Thread.currentThread().getName() + " invoked get() ");

set();

lock.unlock();

lock.unlock();

}

public void set(){

lock.lock();

System.out.println(Thread.currentThread().getName() + " ####invoked set() ");

lock.unlock();

}

}

public class ReenterLockDemo {

public static void main(String[] args) {

Phone phone = new Phone();

new Thread(() -> {

phone.sendSms();

},"t1").start();

new Thread(() -> {

phone.sendSms();

},"t2").start();

//暂停一会

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println();

System.out.println();

System.out.println();

System.out.println();

System.out.println();

Thread t3 = new Thread(phone,"t3");

Thread t4 = new Thread(phone,"t4");

t3.start();

t4.start();

/**

* 14invoked sendSms

* 14#######invoked sendEmail

* 13invoked sendSms

* 13#######invoked sendEmail

*

*

*

*

*

* t3 invoked get()

* t3 ####invoked set()

* t4 invoked get()

* t4 ####invoked set()

*/

}

}

3、读写锁

/**

* @DESCRIPTION 读写锁

*多个线程同时读一个资源关没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行

* 但是如果有一个线程想去写共享资源来,就不应该再有其它线程可以对该资源进行读或写

* 小总结

* 读-读能共存

* 读-写不能共存

* 写不能共存

*

*

* 写操作:原子(完整一致性)+独占,整个过程必须是一个完整的统一体,中间不能间断

*

* @Author lst

* @Date 2020-03-24 12:00

*/

class MyCache { //资源类

private volatile Map map = new HashMap<>();

private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

public void put(String key,Object value){

//写锁

rwLock.writeLock().lock();

try {

System.out.println(Thread.currentThread().getName()+" 正在写入: " +key);

//暂停一会线程

try {

TimeUnit.SECONDS.sleep(3);

} catch (InterruptedException e) {

e.printStackTrace();

}

map.put(key,value);

System.out.println(Thread.currentThread().getName()+" 写入完成: " );

}catch (Exception e){

e.getMessage();

}finally {

rwLock.writeLock().unlock();

}

}

public void get(String key){

//读锁

rwLock.readLock().lock();

try {

System.out.println(Thread.currentThread().getName()+" 正在读取: " +key);

//暂停一会线程

try {

TimeUnit.SECONDS.sleep(3);

} catch (InterruptedException e) {

e.printStackTrace();

}

Object result = map.get(key);

System.out.println(Thread.currentThread().getName()+" 读取完成: " + result);

}catch (Exception e){

e.getMessage();

}finally {

rwLock.readLock().unlock();

}

}

public void clearMap(){

map.clear();

}

}

public class ReentranRreadWriteLockDemo {

public static void main(String[] args) {

MyCache myCache = new MyCache();

for (int i = 0; i < 5; i++) {

final String keyValue = String.valueOf(i);

new Thread(() -> {

myCache.put(keyValue,keyValue);

},keyValue).start();

}

for (int i = 0; i < 5; i++) {

final String keyValue = String.valueOf(i);

new Thread(() -> {

myCache.get(keyValue);

},keyValue).start();

}

/* 0 正在写入: 0

0 写入完成:

1 正在写入: 1

1 写入完成:

2 正在写入: 2

2 写入完成:

3 正在写入: 3

3 写入完成:

4 正在写入: 4

4 写入完成:

0 正在读取: 0

1 正在读取: 1

2 正在读取: 2

3 正在读取: 3

4 正在读取: 4

0 读取完成: 0

1 读取完成: 1

2 读取完成: 2

3 读取完成: 3

4 读取完成: 4

*/

ShareResource shareResource = new ShareResource();

new Thread(() -> {

for (int i = 1; i <= 10; i++) {

shareResource.print5();

}

},"A").start();

new Thread(() -> {

for (int i = 1; i <= 10; i++) {

shareResource.print10();

}

},"B").start();

new Thread(() -> {

for (int i = 1; i <= 10; i++) {

shareResource.print15();

}

},"C").start();

}

}

4、synchronized和lock有什么区别?用新的lock有什么好处?你挙例说说

/**

* 题目: synchronized 和lock有什么区别?用新的lock有什么好处?你挙例说说

* 1、原始构成

* synchronized是关字jvm层面,

* monitorenter(底层是通过monitor对象来完成,其实wait/ notify等方法也依 monitor对象只有在同步块或方法中能源ait/ notify等方

* monitorexit

* Lock是具体类(java,utiL, concurrent. Locks.Lock)是api层面的锁

* 2、使用方法

* synchronized 不需要用户去手动释放锁,当 synchronized代码执行完后系统会自动让线程释放对锁的占用

* Reentrantlock则需要户去手动释放锁,若没有主动释放锁,就有可能导致出现死锁现象。需要Lock()和unLock()方法配合try/ finally语句块来完成

* 3、等待是否可中断

* synchronized 不可中断,除非抛出异常或者正常运行完成

* Reentrantlock 可中断,

* 1.设置超时方法 trylock( long timeout, Timeunit unit)

* 2. LockInterruptibly()放代码块中,调 interrupt()方法可中断

* 4、加锁是否公平

* synchronized非公平锁

* Reentrantlock 两者都可以,默认非公平锁,构造方法可以传入 boolean值,true为公平锁, false为非公平锁

*

* 5、锁绑定多个条件 Condition

* synchronized没有

* Reentrantlock,用来实分组唤要唤的线程,可以精确唤醒,而不是像 synchronized要么随机唤醒一个线程 要么唤醒全部线程

*

*

* 原始构成:synchronized是JVM层面的,底层通过monitorenter和monitorexit来实现的。Lock是JDK API层面的。(synchronized一个enter会有两个exit,一个是正常退出,一个是异常退出(保证肯定可以退出))

* 使用方法:synchronized不需要手动释放锁,而Lock需要手动释放。

* 是否可中断:synchronized不可中断,除非抛出异常或者正常运行完成。Lock是可中断的,1.设置超时方法tryLock(long timeout,TimeUnit unit); 2. lockInterruptibly()方法放代码块中,调用interrupt()

* 是否为公平锁:synchronized只能是非公平锁,而ReentrantLock既能是公平锁,又能是非公平锁,构造方法传入false/true,默认是非公平锁false。

* 绑定多个条件:synchronized不能,只能随机唤醒。而Lock可以通过Condition来绑定多个条件,精确唤醒。

*

*

* 题目:多线程之按顺序调用,实现A->B->C三个线程启动,要求如下

* AA打印5次,BB打印10次,CC打印15次

* 紧接着

* AA打印5次,BB打印10次,CC打印15次

* 。。。。。。

* 来10轮

*

*/

class ShareResource{

private int number = 1;//A:1 B:2 C:3

private Lock lock = new ReentrantLock();

private Condition c1 = lock.newCondition();

private Condition c2 = lock.newCondition();

private Condition c3 = lock.newCondition();

public void print5(){

lock.lock();

try{

//1、判断

while (number != 1){

c1.await();

}

//2、干活

for (int i = 1; i <= 5 ; i++) {

System.out.println(Thread.currentThread().getName()+" " + i);

}

//3、通知

number = 2;

c2.signal();

}catch (Exception e){

e.printStackTrace();

}finally {

lock.unlock();

}

}

public void print10(){

lock.lock();

try{

//1、判断

while (number != 2){

c2.await();

}

//2、干活

for (int i = 1; i <= 10 ; i++) {

System.out.println(Thread.currentThread().getName()+" " + i);

}

//3、通知

number = 3;

c3.signal();

}catch (Exception e){

e.printStackTrace();

}finally {

lock.unlock();

}

}

public void print15(){

lock.lock();

try{

//1、判断

while (number != 3){

c3.await();

}

//2、干活

for (int i = 1; i <= 15 ; i++) {

System.out.println(Thread.currentThread().getName()+" " + i);

}

//3、通知

number = 1;

c3.signal();

}catch (Exception e){

e.printStackTrace();

}finally {

lock.unlock();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值