在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制。

  1. 对象锁

所有对象都自动含有单一的锁。

JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。

只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。

  1. 类锁

对于同步静态方法/静态变量互斥体,由于一个class不论被实例化多少次,其中的静态方法和静态变量在内存中都只由一份。所以,一旦一个静态的方法被申明为synchronized。此类所有的实例化对象在调用此方法,共用同一把锁,我们称之为类锁。一旦一个静态变量被作为synchronized block的互斥体。进入此同步区域时,都要先获得此静态变量的对象锁。

由上述同步静态方法引申出一个概念,那就是类锁。其实系统中并不存在什么类锁。当一个同步静态方法被调用时,系统获取的其实就是代表该类的类对象的对象锁

可以尝试用以下方式获取类锁

synchronized (xxx.class) {…}

synchronized (Class.forName(“xxx”)) {…} 123

若要同时获取两种锁,同时获取类锁和对象锁是允许的,并不会产生任何问题,但使用类锁时一定要注意,一旦产生类锁的嵌套获取的话,就会产生死锁,因为每个class在内存中都只能生成一个Class实例对象。

  1. synchronized同步块

3.1. 同步到单一对象锁

当使用同步块时,如果方法下的同步块都同步到一个对象上的锁,则所有的任务(线程)只能互斥的进入这些同步块。
Resource1.Java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,虽然这些同步块处在不同的方法中,但由于是同步到同一个对象(当前对象 synchronized (this)),所以对它们的方法依然是互斥的。
Resource1.java

package com.zj.lock;
import java.util.concurrent.TimeUnit;

public class Resource1 {
public void f() {
// other operations should not be locked…
System.out.println(Thread.currentThread().getName()
+ “:not synchronized in f()”);
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()
+ “:synchronized in f()”);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public void g() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in g()");  synchronized (this) {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in g()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }
}  public void h() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in h()");  synchronized (this) {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in h()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }
}  public static void main(String[] args) {  final Resource1 rs = new Resource1();  new Thread() {  public void run() {  rs.f();  }  }.start();  new Thread() {  public void run() {  rs.g();  }  }.start();  rs.h();
}

} 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273

结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
Thread-1:not synchronized in g()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()

3.2. 同步到多个对象锁

Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,这些同步块处在不同的方法中,并且是同步到三个不同的对象(synchronized (this),synchronized(syncObject1),synchronized (syncObject2)),所以对它们的方法中的临界资源访问是独立的。
Resource2.java

package com.zj.lock;
import java.util.concurrent.TimeUnit;

public class Resource2 {
private Object syncObject1 = new Object();
private Object syncObject2 = new Object();

public void f() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in f()");  synchronized (this) {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in f()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }
}  public void g() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in g()");  synchronized (syncObject1) {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in g()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }
}  public void h() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in h()");  synchronized (syncObject2) {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in h()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }
}  public static void main(String[] args) {  final Resource2 rs = new Resource2();  new Thread() {  public void run() {  rs.f();  }  }.start();  new Thread() {  public void run() {  rs.g();  }  }.start();  rs.h();
}

}

结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
main:synchronized in h()
Thread-1:not synchronized in g()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()

  1. Lock对象锁

除了使用synchronized外,还可以使用Lock对象来创建临界区。Resource3.java的演示效果同Resource1.java;Resource4.java的演示效果同Resource2.java。
Resource3.java

package com.zj.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Resource3 {
private Lock lock = new ReentrantLock();

public void f() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in f()");  lock.lock();  try {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in f()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  } finally {  lock.unlock();  }
}  public void g() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in g()");  lock.lock();  try {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in g()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  } finally {  lock.unlock();  }
}  public void h() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in h()");  lock.lock();  try {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in h()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  } finally {  lock.unlock();  }
}  public static void main(String[] args) {  final Resource3 rs = new Resource3();  new Thread() {  public void run() {  rs.f();  }  }.start();  new Thread() {  public void run() {  rs.g();  }  }.start();  rs.h();
}

结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
Thread-1:not synchronized in g()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()

Resource4.java

package com.zj.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Resource4 {
private Lock lock1 = new ReentrantLock();
private Lock lock2 = new ReentrantLock();
private Lock lock3 = new ReentrantLock();

public void f() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in f()");  lock1.lock();  try {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in f()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  } finally {  lock1.unlock();  }
}  public void g() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in g()");  lock2.lock();  try {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in g()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  } finally {  lock2.unlock();  }
}  public void h() {  // other operations should not be locked...  System.out.println(Thread.currentThread().getName()  + ":not synchronized in h()");  lock3.lock();  try {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName()  + ":synchronized in h()");  try {  TimeUnit.SECONDS.sleep(3);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  } finally {  lock3.unlock();  }
}  public static void main(String[] args) {  final Resource4 rs = new Resource4();  new Thread() {  public void run() {  rs.f();  }  }.start();  new Thread() {  public void run() {  rs.g();  }  }.start();  rs.h();
}

}

结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
main:synchronized in h()
Thread-1:not synchronized in g()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()

另外,ReentrantLock可定时和可轮询的锁获取模式由tryLock方法实现。

public boolean tryLock(); //等同于tryLock(0, TimeUnit.SECONDS),不停询问是否可获取锁
public boolean tryLock(long timeout,
TimeUnit unit)
throws InterruptedException //timeout - 等待锁的时间,unit - timeout 参数的时间单位 1234

  1. synchronized和lock的区别:

Lock 的锁定是通过代码实现的,而 synchronized 是在 JVM 层面上实现的。

synchronized 在锁定时如果方法块抛出异常,JVM 会自动将锁释放掉,不会因为出了异常没有释放锁造成线程死锁。但是 Lock 的话就享受不到 JVM 带来自动的功能,出现异常时必须在 finally 将锁释放掉,否则将会引起死锁。

在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。

ReentrantLock:

ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。

Atomic:

和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。
关于synchronized和lock的详细区别请看http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html

转自:http://blog.csdn.net/ymeng_bupt/article/details/6826936

类锁 synchronized对象锁 和 Lock对象锁相关推荐

  1. 【并发编程】线程锁--Synchronized、ReentrantLock(可重入锁)

    在说锁之前,我们要明白为什么要加锁,不加锁会怎样? 在并发编程中,很容易出现线程安全问题,接下来我们看个很经典的例子--银行取钱,来看一下有关线程安全的问题. 取钱的流程可以分为一下几个步骤: 1.用 ...

  2. Java:使用synchronized和Lock对象获取对象锁

    在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制. 1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁 ...

  3. 使用synchronized和Lock对象获取对象锁

     Java:使用synchronized和Lock对象获取对象锁 下面使用ReentrantLock这个锁来实现加锁功能: package com.tch.test.concurrent;import ...

  4. Java多线程----java 对象锁(synchronized/lock)

    在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制. 1. 对象锁 所有对象都自动含有单一的锁.      JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次 ...

  5. java中锁的基本原理和升级:偏向锁、轻量级锁、重量级锁

    目录 由一个问题引发的思考 多线程对于共享变量访问带来的安全性问题 线程安全性 思考如何保证线程并行的数据安全性 synchronized 的基本认识 synchronized 的基本语法 synch ...

  6. Java锁Synchronized对象锁和类锁区别(搬运)

    java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保 ...

  7. 【本人秃顶程序员】synchronized锁住的是代码还是对象

    ←←←←←←←←←←←← 快!点关注 不同的对象 public class Sync {public synchronized void test() {System.out.println(&quo ...

  8. Java线程同步:synchronized锁住的是代码还是对象

    在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行.synchronized既可以加在一段代码上,也可以加在 ...

  9. java lock 对象_Java并发编程锁系列之ReentrantLock对象总结

    Java并发编程锁系列之ReentrantLock对象总结 在Java并发编程中,根据不同维度来区分锁的话,锁可以分为十五种.ReentranckLock就是其中的多个分类. 本文主要内容:重入锁理解 ...

最新文章

  1. VMware里的linux系统里的命令行里会有bee的声音,要如何关掉
  2. 1045 Favorite Color Stripe(LIS解法)
  3. java collections.sort 忽略大小写排序_Java Spring Mongo排序忽略大小写问题
  4. 如何使用 Java 生成二维码?
  5. java 判断是否是list_JAVA从头开始一基础梳理(4-3)
  6. python七巧板三角形_用七巧板拼出14种三角形,这才是图形认知的神器!
  7. python 获取数据库字段类型_python中如何读取数据库数据类型
  8. html块级页面居中,几个并排div的CSS / HTML居中
  9. matlab中的取整函数(ceil、floor、round)
  10. CDN技术原理 CDN细节特点
  11. 【跟我一起学Linux之Ubuntu】-概述与安装配置笔记
  12. 7-2 单位年会聚餐时的座次C位
  13. Matplotlib直方图
  14. monocle安装不成功 想尽各种办法
  15. STM32F030C8T6单片机与GY-61 ADXL335模块——角度传感器
  16. IE浏览器无法下载word和pdf文件的解决办法
  17. 一步步演示Avantage软件如何处理XPS谱图!
  18. CSS小技巧-为内盒子添加margin-top时,会带着父盒子一起下来,如何解决?
  19. 网页设计常用的12中颜色
  20. 实现原理 扫描枪_扫描枪的工作原理

热门文章

  1. kplay - 一款可实时调音的免费开源的wav文件播放器
  2. RPA应用于电力行业的优势:来自3大应用场景的解读
  3. 克鲁斯卡尔算法求最小生成树
  4. 目标检测 - 基于 SSD: Single Shot MultiBox Detector 的人体上下半身检测
  5. Integer 与 Int 的区别
  6. Java 和操作系统交互细节
  7. 阿姆斯特朗配货站欺诈邮政赔1亿美元
  8. 游戏是如何让你上瘾的
  9. python 处理url 参数_python模块 furl 使得操纵URL简单化,去除网址中参数
  10. CIFAR10数据集转化为图片