Java多线程之synchronzied锁和Lock锁


提示:以下是本篇文章正文内容,Java系列学习将会持续更新

一、synchronzied

什么是锁?

为了解决线程不安全的问题,JVM设置了一种机制。当一个线程对共享数据进行操作时,其他线程不能参加,直到等A线程操作完毕才能依次进行,也就是同步机制

synchronized的作用:实现线程同步,让多个线程排序依次获取共享资源,防止共享数据出错。

互斥锁:即能达到互斥访问目的的锁,也就是说当一个共享数据被当前正在访问的线程加上互斥锁后,在同一个时刻,其他线程只能处于等待的状态,直到当前线程处理完毕释放该锁。

互斥条件多个线程都有加锁操作 && 锁的是同一个对象

syn语法

修饰方法

// 静态方法,锁定的是类
synchronized static void fun1() { }
// 非静态方法,锁定的是方法的调用者
synchronized void fun2() { }

修饰代码块,锁定的是传入的对象

Object o1 = new Object();
void fun3() {
    synchronized (o1) { }
}
void fun4() {
    synchronized (Test.class) { }
}

在这里插入图片描述
JVM对所有的类都实现了“锁”的功能
如何正确加锁?
七个场景,有对有错

回到目录…

syn的工作原理

在这里插入图片描述

syn加锁的作用

1.原子性(90%):将需要保证原子性的操作互斥起来
在这里插入图片描述
加锁粒度越细,并发性越高。但并不一定粒度越细越好。

2.可见性(5%)
在这里插入图片描述

3.重排序(5%)
在这里插入图片描述

回到目录…

二、Lock

Lock锁的使用

Lock是JDK1.5出现的一种锁的实现方式,是一个接口。弥补了syn使用中的不足。
实现类:ReentrantLock, ReadLock, WriteLock

java.util.concurrent.locks.Lock
void lock();获取锁。效果等同于syn
void lockInterruptibly();加锁并且线程允许被中断。
boolean tryLock();尝试去加锁,失败返回false。
boolean tryLock(long time,TimeUnit unit);在等待时间内加锁。等待过程允许被中断
void unlock();释放锁。

ReentrantLock的使用:

/**
 * ReentrantLock的使用
 */
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Demo1 {

    // 定义一个被操作的数
    static int r = 0;
    // 定义操作的数
    static final int COUNT = 1000_0000;

    static class Add extends Thread {

        Lock o;
        Add(Lock o) {
            this.o = o;
        }

        @Override
        public void run() {
            o.lock(); // 获取锁
            try {
                for (int i = 0; i < COUNT; i++) {
                    r++;
                }
            }finally { // 将解锁操作放在finally中,确保任何情况都可以进行
                o.unlock(); // 释放锁
            }
        }
    }

    static class Sub extends Thread {

        Lock o;
        Sub(Lock o) {
            this.o = o;
        }

        @Override
        public void run() {
            o.lock(); // 加锁
            try {
                for (int i = 0; i < COUNT; i++) {
                    r--;
                }
            } finally {
                o.unlock(); // 解锁
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {

		// 定义一个锁对象
        Lock o = new ReentrantLock();

		// 将锁传入线程中
        Thread add = new Add(o);
        add.start();
        Thread sub = new Sub(o);
        sub.start();

        // 等待结束
        add.join();
        sub.join();

        // 加锁后线程安全
        System.out.println(r);
        // 加锁使得两个线程互斥执行
    }
}

Lock比synchronized更灵活
Lock的多种应用场景

死锁

 所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。

造成死锁的原因
 ·当前线程拥有其他线程需要的资源
 ·当前线程等待其他线程已拥有的资源
 ·都不放弃自己拥有的资源

避免死锁的三种技术
 ·加锁顺序(线程按照一定的顺序加锁)
 ·加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
 ·死锁检测(tryLock())

三、syn锁 vs JUC锁

synchronziedJuc包下的锁
来源Java内置的关键字继承了Lock接口,有很多实现类
代码语法自动释放锁需要手动释放锁
灵活程度比较单一可以在一个方法中加锁,到另一个方法中解锁
锁的类型syn是独占锁、可重入锁、非公平锁锁的类型更多:公平锁/非公平锁、读写锁/独占锁、可重入锁/不可重入锁
加锁策略只能请求锁加锁策略灵活:请求锁、可中断的锁、尝试锁、请求失败
线程间通信Object类中的wait()和notify()Condition对象的await()和signal()

回到目录…


总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是Java多线程的学习,认识了什么是锁,关键字synchronized和Lock这两种锁的用法。之后的学习内容将持续更新!!!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只咸鱼。。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值