同步锁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线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...
随机推荐
- remove CMakeCache.txt and rerun cmake.On Debian/Ubuntu, package name is libncurses5-dev, on Redhat and derivates it is ncurses-devel.
如果cmake提示下列错误:......CMake Error at cmake/readline.cmake:85 (MESSAGE): Curses library not found. Pl ...
- Linux~其实shell脚本也很简单
用了两个的centos之后,也想看看它的脚本,我们知道shell这个东西就像windows里的批处理,它可以将一些语句进行组合,然后统一去执行,感觉挺方便的. shell文件的组成 shell语言环境 ...
- Django中的templates(你的HTML页面放哪里)
本文回答Django里面的HTML文件应该怎么放,以及Django是如何查找模板文件的. 到目前为止我们没有使用HTML页面,在之前的说明中所有内容都是写死在程序里的,如果你想改变内容就要修改代码.但 ...
- 微服务实战(二):使用API Gateway
微服务实战(一):微服务架构的优势与不足 微服务实战(二):使用API Gateway 微服务实战(三):深入微服务架构的进程间通信 微服务实战(四):服务发现的可行方案以及实践案例 微服务实践(五) ...
- eclipse 创建maven 项目 动态web工程完整示例 maven 整合springmvc整合mybatis
接上一篇: eclipse 创建maven 项目 动态web工程完整示例 eclipse maven工程自动添加依赖设置 maven工程可以在线搜索依赖的jar包,还是非常方便的 但是有的时候可能还需 ...
- NiftyNet 数据预处理
NiftyNet项目介绍 使用NiftyNet时,我们需要先将图像数据和标签进行一次简单的处理,得到对应的.csv文件. 对应文件格式为: img.csv image path img_name im ...
- 痞子衡嵌入式:ARM Cortex-M文件那些事(3)- 工程文件(.ewp)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的project文件. 前面两节课里,痞子衡分别给大家介绍了嵌入式开发中的两种典型input文件:源文件(.c/.h/.s). ...
- 字符串string 、byte[]、MemoryStream、Base64String的相互转换
1.字符串转比特数组 (1)byte[] bt=System.Text.Encoding.Default.GetBytes("字符串"); (2)byte[] bt=Convert ...
- C# asp.net mvc 通过 HttpClient 访问 Web_API
//MVC 具体方法 //API地址 通过 WebConfig配置 private static string apiAdds = ConfigurationManager.AppSettings[& ...
- wpf 无缝滚动
很早以前有项目就需要文字无缝滚动的效果但无奈当时技术不到位 人也比较懒惰(大概程序猿都是这个样子吧) 此方法并非只文字无缝其实任何内容都可以 <ScrollViewer Name="s ...