博客已迁移到CSDN《https://blog.csdn.net/qq_33375499

 在java中,解决同步问题,很多时候都会使用到synchronized和Lock,这两者都是在多线程并发时候常使用的锁机制。

 synchronized是java中的一个关键字,也就是说是java内置的一个特性。当一个线程访问一个被synchronized修饰的代码块,会自动获取对应的一个锁,并在执行该代码块时,其他线程想访问这个代码块,会一直处于等待状态,自有等该线程释放锁后,其他线程进行资源竞争,竞争获取到锁的线程才能访问该代码块。

  线程释放synchronized修饰的代码块锁的方式有两种:

  1. 该线程执行完对应代码块,自动释放锁。
  2. 在执行该代码块是发生了异常,JVM会自动释放锁。

  采用synchronized关键字来实现同步,会导致如果存在多个线程想执行该代码块,而当前获取到锁的线程又没有释放锁,可想而知,其他线程只有一只等待,这将严重印象执行效率。Lock锁机制的出现就是为了解决该现象。Lock是一个java接口,通过这个接口可以实现同步,使用Lock时,用户必须手动进行锁的释放,否则容易出现死锁。

  ReentranLock是Lock的唯一实现类。下面简单介绍一下ReentranLock与synchronized的区别:

  • Synchronized是一个同步锁。当一个线程A访问synchronized修饰的代码块时,线程A就会获取该代码块的锁,如果这时存在其他线程范围该代码块时,将会阻塞,但是不影响这些线程访问其他非同步代码块。
  • ReentranLock是可重入锁。由构造方法可知,该锁支持两种锁模式,公平锁和非公平锁。默认是非公平的。

  公平锁:当线程A获取访问该对象,获取到锁后,此时内部存在一个计数器num+1,其他线程想访问该对象,就会进行排队等待(等待队列最前一个线程处于待唤醒状态),直到线程A释放锁(num = 0),此时会唤醒处于待唤醒状态的线程进行获取锁的操作,一直循环。如果线程A再次尝试获取该对象锁是,会检查该对象锁释放已经被占用,如果被占用,会做一次是否为当前线程占用锁的判断,如果是内部计数器num+1,并且不需要进入等待队列,而是直接回去当前锁。

  非公平锁:当线程A在释放锁后,等待对象的线程会进行资源竞争,竞争成功的线程将获取该锁,其他线程继续睡眠。

  公平锁是严格的以FIFO的方式进行锁的竞争,但是非公平锁是无序的锁竞争,刚释放锁的线程很大程度上能比较快的获取到锁,队列中的线程只能等待,所以非公平锁可能会有“饥饿”的问题。但是重复的锁获取能减小线程之间的切换,而公平锁则是严格的线程切换,这样对操作系统的影响是比较大的,所以非公平锁的吞吐量是大于公平锁的,这也是为什么JDK将非公平锁作为默认的实现。

  下面是接口Lock的方法:

  

  附上对接口Lock方法的测试,有什么问题欢迎各位大佬留言评论。

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class TestLock {
// ReentrantLock为Lock的唯一实现类
private Lock lock = new ReentrantLock(); /**
* 测试使用lock 的 lock()方法 :如果锁已经被其他线程获取,则等待
* @param thread
*/
public void testLock(Thread thread){
try {
// 1.获取锁
lock.lock();
System.out.println("线程 " + thread.getName() + " 获取了锁!");
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("线程 " + thread.getName() + " 释放了锁!");
// 必须在 finally 中释放锁,防止死锁
lock.unlock();
}
} /**
* 测试使用lock 的 lock()方法 :通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。
* @param thread
*/
public void testLockInterruptibly(Thread thread){
try {
// 1.获取锁
lock.lockInterruptibly();
System.out.println("线程 " + thread.getName() + " 获取了锁!");
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("线程 " + thread.getName() + " 释放了锁!");
// 必须在 finally 中释放锁,防止死锁
lock.unlock();
}
} /**
* 测试使用lock 的 tryLock()方法 :如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false
* @param thread
*/
public void testTryLock(Thread thread){
if(lock.tryLock()){// 如果获取到了锁
try {
System.out.println("线程 " + thread.getName() + " 获取了锁!");
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("线程 " + thread.getName() + " 释放了锁!");
// 必须在 finally 中释放锁,防止死锁
lock.unlock();
}
}else {
// 没有获取到锁
System.out.println("线程 " + thread.getName() + " 没有获取到锁!");
}
} /**
* 测试使用lock 的 tryLock(long time, TimeUnit unit)方法 :和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,
* 在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
* @param thread
*/
public void testTryLock_time_unit(Thread thread){
try {
if(lock.tryLock(1000, TimeUnit.MILLISECONDS)){// 如果获取到了锁
try {
System.out.println("线程 " + thread.getName() + " 获取了锁!");
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("线程 " + thread.getName() + " 释放了锁!");
// 必须在 finally 中释放锁,防止死锁
lock.unlock();
}
}else {
// 没有获取到锁
System.out.println("线程 " + thread.getName() + " 没有获取到锁!");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} public static void main(String[] args){
TestLock testLock = new TestLock();
Thread a = new Thread("A") {
@Override
public void run() {
/*// 测试 lock()
testLock.testLock(Thread.currentThread());*/
/*// 测试 lockInterruptibly()
testLock.testLockInterruptibly(Thread.currentThread());*/
/*// 测试 tryLock()
testLock.testTryLock(Thread.currentThread());*/
/*// 测试 tryLock(long time, TimeUnit unit)
testLock.testTryLock_time_unit(Thread.currentThread());*/
testLock.testTryLock_time_unit(Thread.currentThread());
}
};
Thread b = new Thread("B") {
@Override
public void run() {
testLock.testTryLock(Thread.currentThread());
}
};
a.start();
b.start();
}
}

java 锁机制(synchronized 与 Lock)的更多相关文章

  1. Java 锁机制 synchronized

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/75126630 本文出自[赵彦军的博客] 1.前言 在多线程并发编程中Synchro ...

  2. 转 : 深入解析Java锁机制

    深入解析Java锁机制 https://mp.weixin.qq.com/s?__biz=MzU0OTE4MzYzMw%3D%3D&mid=2247485524&idx=1&s ...

  3. Java 锁机制总结

    锁的种类 独享锁 VS 共享锁 独享锁:锁只能被一个线程持有(synchronized) 共享锁:锁可以被多个程序所持有(读写锁) 乐观锁 VS 悲观锁 乐观锁:每次去拿数据的时候都乐观地认为别人不会 ...

  4. Java锁机制深入理解

    Java锁机制 背景知识 指令流水线 ​ CPU的基本工作是执行存储的指令序列,即程序.程序的执行过程实际上是不断地取出指令.分析指令.执行指令的过程. ​ 几乎所有的冯•诺伊曼型计算机的CPU,其工 ...

  5. java锁机制的面试题

    java锁机制的面试题 1.ABA问题 2.CAS乐观锁 3.synchronize实现原理 4.synchronize与lock的区别 5.volatile实现原理 6.乐观锁的业务场景及实现方式 ...

  6. InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析

    InnoDB锁机制之Gap Lock.Next-Key Lock.Record Lock解析 有意思,解释的很好

  7. 从synchronized和lock区别入手聊聊java锁机制

    写这篇文章之前,我去百度了一下啥叫锁,百度百科上写道:置于可启闭的器物上,以钥匙或暗码开启.确实我们一般理解的锁就是门锁,密码锁,但是在计算机科学中,锁又是啥,说实话,这个问题我也思考了很久,也没法很 ...

  8. java多线程(五)-访问共享资源以及加锁机制(synchronized,lock,voliate)

    对于单线程的顺序编程而言,每次只做一件事情,其享有的资源不会产生什么冲突,但是对于多线程编程,这就是一个重要问题了,比如打印机的打印工作,如果两个线程都同时进行打印工作,那这就会产生混乱了.再比如说, ...

  9. java的锁机制——synchronized

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线 ...

随机推荐

  1. C语言中指针的加减运算

    参考文章,值得一看 char arr[3]; printf("arr:\n%d\n%d\n%d\n", arr, arr + 1, arr + 2); char *parr[3]; ...

  2. IDLE in Python (Ubuntu)

    To lauch IDLE in the Current Woking Directory >>> usr/bin/idle3 Alt + n  # next command Alt ...

  3. nyoj 93 汉诺塔(三)(stack)

    汉诺塔(三) 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度 ...

  4. [luoguP1280] 尼克的任务(DP)

    传送门 原本想着 f[i] 表示前 i 个任务的最优答案,但是不好转移 看了题解后,发现是 f[i] 表示前 i 分钟的最优解,看来还是不能死脑筋,思维得活跃,一个思路行不通就换一个思路. 把 f 数 ...

  5. [luoguP3203][HNOI2010]BOUNCE 弹飞绵羊(LCT)

    传送门 每个点都会跳到另一个点,连边就是一棵树. 更改弹力就是换边. 求一个点跳多少次跳到终点就是求这个点的深度,那么只需要维护 size 域,access(n + 1) 然后 splay(x),求 ...

  6. (12)GrabCut前景提取

    import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('opencv-python-foregr ...

  7. Java AOP 获取HttpSevletRequest、HttpSevletResponse、HttpSession对象

    ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) ((ServletRequestAttributes) ...

  8. 函数式语言(functional language)定义、函数式语言的种类以及为什么函数式语言会流行起来的学习笔记

    一.什么是函数式语言?       函数式语言一类程序设计语言,是一种非冯·诺伊曼式的程序设计语言.函数式语言主要成分是原始函数.定义函数和函数型.这种语言具有较强的组织数据结构的能力,可以把某一数据 ...

  9. - > 贪心基础入门讲解二——活动安排问题

    有若干个活动,第i个开始时间和结束时间是[Si,fi),只有一个教室,活动之间不能交叠,求最多安排多少个活动? 分析: 我们就是想提高教室地利用率,尽可能多地安排活动.考虑容易想到的几种贪心策略: ( ...

  10. 常见mysql的数据迁移

    1.处理把A表中的部分列复制到B表中主要处理同一库. UPDATE T_EVENT EVE, T_IPMAP MAP SET EVE.c_staff_code = MAP.c_staff_code, ...