同步锁Synchronized与Lock的区别?
synchronized与Lock两者区别:
1:Lock是一个接口,而Synchronized是关键字。
2:Synchronized会自动释放锁,而Lock必须手动释放锁。
3:Lock可以让等待锁的线程响应中断,而Synchronized不会,线程会一直等待下去。
4:通过Lock可以知道线程有没有拿到锁,而Synchronized不能。
5:Lock能提高多个线程读操作的效率。
6:Synchronized能锁住类、方法和代码块,而Lock是块范围内的
/**
* synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
* lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类
* 作为对象才能保证锁的生效。
* 且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
*
* synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。
* 而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低
* Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,
* 如果因为冲突失败就重试,直到成功为止。
* 乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,
* 会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令
*/
再看具体代码小例子:
package com.cn.test.thread.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
private Lock lock = new ReentrantLock();
/*
* 使用完毕释放后其他线程才能获取锁
*/
public void lockTest(Thread thread) {
lock.lock();//获取锁
try {
System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称
Thread.sleep(2000);//为看出执行效果,是线程此处休眠2秒
} catch (Exception e) {
System.out.println("线程"+thread.getName() + "发生了异常释放锁");
}finally {
System.out.println("线程"+thread.getName() + "执行完毕释放锁");
lock.unlock(); //释放锁
}
}
public static void main(String[] args) {
LockTest lockTest = new LockTest();
//声明一个线程 “线程一”
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
lockTest.lockTest(Thread.currentThread());
}
}, "thread1");
//声明一个线程 “线程二”
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
lockTest.lockTest(Thread.currentThread());
}
}, "thread2");
// 启动2个线程
thread2.start();
thread1.start();
}
}
执行结果:
package com.cn.test.thread.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class LockTest {
private Lock lock = new ReentrantLock(); /*
* 尝试获取锁 tryLock() 它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false
*/
public void tryLockTest(Thread thread) {
if(lock.tryLock()) { //尝试获取锁
try {
System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称
Thread.sleep(2000);//为看出执行效果,是线程此处休眠2秒
} catch (Exception e) {
System.out.println("线程"+thread.getName() + "发生了异常释放锁");
}finally {
System.out.println("线程"+thread.getName() + "执行完毕释放锁");
lock.unlock(); //释放锁
}
}else{
System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,我无法获取");
}
}
public static void main(String[] args) {
LockTest lockTest = new LockTest();
//声明一个线程 “线程一”
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
lockTest.tryLockTest(Thread.currentThread());
}
}, "thread1");
//声明一个线程 “线程二”
Thread thread2 = new Thread(new Runnable() { @Override
public void run() {
lockTest.tryLockTest(Thread.currentThread());
}
}, "thread2");
// 启动2个线程
thread2.start();
thread1.start(); }
}
执行结果:
package com.cn.test.thread.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class LockTest {
private Lock lock = new ReentrantLock();
public void tryLockParamTest(Thread thread) throws InterruptedException {
if(lock.tryLock(3000, TimeUnit.MILLISECONDS)) { //尝试获取锁 获取不到锁,就等3秒,如果3秒后还是获取不到就返回false
try {
System.out.println("线程"+thread.getName() + "获取当前锁"); //打印当前锁的名称
Thread.sleep(4000);//为看出执行效果,是线程此处休眠2秒
} catch (Exception e) {
System.out.println("线程"+thread.getName() + "发生了异常释放锁");
}finally {
System.out.println("线程"+thread.getName() + "执行完毕释放锁");
lock.unlock(); //释放锁
}
}else{
System.out.println("我是线程"+Thread.currentThread().getName()+"当前锁被别人占用,等待3s后仍无法获取,放弃");
}
}
public static void main(String[] args) {
LockTest lockTest = new LockTest();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
lockTest.tryLockParamTest(Thread.currentThread());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "thread1");
//声明一个线程 “线程二”
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
lockTest.tryLockParamTest(Thread.currentThread());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, "thread2");
// 启动2个线程
thread2.start();
thread1.start();
}
}
执行结果:
因为此时线程1休眠了4秒,线程2等待了3秒还没有获取到就放弃获取锁了,执行结束
将方法中的 Thread.sleep(4000)改为Thread.sleep(2000)执行结果如下:
因为此时线程1休眠了2秒,线程2等待了3秒的期间线程1释放了锁,此时线程2获取到锁,线程2就可以执行了
同步锁Synchronized与Lock的区别?的更多相关文章
- 详解synchronized与Lock的区别与使用
知识点 1.线程与进程 在开始之前先把进程与线程进行区分一下,一个程序最少需要一个进程,而一个进程最少需要一个线程.关系是线程–>进程–>程序的大致组成结构.所以线程是程序执行流的最小单位 ...
- Java synchronized和 Lock 的区别与用法
在分布式开发中,锁是线程控制的重要途径.Java为此也提供了2种锁机制,synchronized和lock.做为Java爱好者,自然少不了对比一下这2种机制,也能从中学到些分布式开发需要注意的地方. ...
- (转)synchronized和lock的区别
背景:最近在准备java基础知识,对于可重入锁一直没有个清晰的认识,有必要对这块知识进行总结. 1 . 什么是可重入锁 锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保 ...
- Synchronized和lock的区别和用法
一.synchronized和lock的用法区别 (1)synchronized(隐式锁):在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要 ...
- Synchronized与Lock的区别与应用场景
转载. https://blog.csdn.net/fly910905/article/details/79765381 同步代码块,同步方法,或者是用java提供的锁机制,我们可以实现对共享资源变量 ...
- synchronized 与 lock 的区别
synchronized 和 lock 的用法区别 synchronized(隐式锁):在需要同步的对象中加入此控制,synchronized 可以加在方法上,也可以加在特定代码块中,括号中表示需要锁 ...
- java - synchronized与lock的区别
synchronized与lock的区别 原始构成 synchronized是关键字属于JVM层面 monitorenter(底层是通过monitor对象来完成,其实wait/notify等对象也依赖 ...
- Java中synchronized和Lock的区别
synchronized和Lock的区别synchronize锁对象可以是任意对象,由于监视器方法必须要拥有锁对象那么任意对象都可以调用的方法所以将其抽取到Object类中去定义监视器方法这样锁对象和 ...
- Java多线程简析——Synchronized(同步锁)、Lock以及线程池
Java多线程 Java中,可运行的程序都是有一个或多个进程组成.进程则是由多个线程组成的.最简单的一个进程,会包括mian线程以及GC线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...
随机推荐
- 『Two 树的直径求解及其运用』
树的直径 我们先来认识一下树的直径. 树是连通无环图,树上任意两点之间的路径是唯一的.定义树上任意两点\(u, v\)的距离为\(u\)到\(v\)路径上边权的和.树的直径\(MN\)为树上最长路径, ...
- Python爬虫入门教程 5-100 27270图片爬取
27270图片----获取待爬取页面 今天继续爬取一个网站,http://www.27270.com/ent/meinvtupian/ 这个网站具备反爬,so我们下载的代码有些地方处理的也不是很到位, ...
- 序列化Serializable和Parcelable
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单记录下序列化Serializable和Parcelable的使用方法. Android中Intent如果要传递类对象,可以通过两 ...
- 带着萌新看springboot源码8(spring ioc源码 完)
上一节说到实例化了所有的单实例Bean,后面还有一步遍历 12.完成容器刷新(finishRefresh();) 那个和生命周期有关的后置处理器类型是LifecycleProcessor:监听器原理我 ...
- Java开发知识之Java编程基础
Java开发知识之Java编程基础 一丶Java的基础语法 每个语言都有自己的语法规范.例如C++ 入口点是main. 我们按照特定格式编写即可. Java也不例外. Java程序的语法规范就是 Ja ...
- Thread之九:stop
搞过Java线程的人都知道,stop这个方法是臭名昭著了,早就被弃用了,但是现在任然有很多钟情与他的人,永远都放不下他,因为从他的字面意思上我们可以知道他貌似可以停止一个线程,这个需求是每个搞线程开发 ...
- Service Worker MDN英文笔记
前言: 以前学习基础知识的时候总看别人写的入门文章,但有时候还是一脸懵逼,直到自己用心阅读了MDN的英文文档才对基础知识的一些理论有了更深的理解,所以我在边阅读文档的时候边记录下帮助比较大的,也方便大 ...
- MySQL高可用复制管理工具 —— Orchestrator介绍
背景 在MySQL高可用架构中,目前使用比较多的是Percona的PXC,Galera以及MySQL 5.7之后的MGR等,其他的还有的MHA,今天介绍另一个比较好用的MySQL高可用复制管理工具:O ...
- App阅读pdf和扫描二维码功能
在之前开发的Android手机App中,需要实现阅读pdf和扫描二维码的功能,在github 上找到大牛封装好包,亲测可用. 阅读pdf: https://github.com/barteksc/An ...
- EF三种编程方式的区别Database first ,Model first ,code first
首先对于EF中先出现的datebase first和model first两种编程方式,其的区别根据字面意思很容易能够理解. datebase first就是代表数据库优先,那么前提就是先创建数据 ...