在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制。
1.对象的锁
所有对象都自动含有单一的锁。
JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。
只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。
2.synchronized同步块
synchronized有两种格式:

格式1:
synchronized(任何对象){
  //访问共享变量的临界区(程序段),又称同步代码块
}
格式2:同步化方法。在方法的前面加上synchronized,如:
public synchronized void add() {
//临界区
}
共享变量所关联的对象锁是如何选择的?即
synchronized (任何对象) {
//临界区
}
  1.synchronized锁定的是一个具体对象,通常是共享变量的对象。用synchronized括起来的程序段是访问该共享变量的临界区,即synchronized代码块。由于所有锁定同一个对象的线程之间,在synchronized代码块上是互斥的,也就是说,这些线程的synchronized代码块之间是串行执行的,不再是互相交替穿插并发执行,因而保证了synchronized 代码块操作的原子性。但synchronized代码块与所有线程的非synchronized 代码块之间以及非synchronized代码块与非synchronized代码块之间都是互相交替穿插并发执行的,故synchronized代码块操作的原子性是逻辑上的,而不是物理上的不可打断。

 2.每一个Java对象都有且只有一个对象锁。任何时刻,一个对象锁只能被一个线程所拥有。若两个或多个线程锁定的不是同一个对象,则它们的synchronized代码块可以互相交替穿插并发执行。
 
3.所有的非synchronized代码块或方法,都可自由调用。如线程A获得了对象锁,调用需要该对象锁的synchronized代码块,其他线程仍然可以自由调用所有非synchronized方法和代码
 
4.若线程A获得了对象O的对象锁,调用对象O的synchronized代码块或方法,则线程A仍然可以调用其他任何需要对象O的锁的synchronized代码块或方法,这是因为线程A已经获得了对象O的对象锁了。线程A同时可以调用需要另一个对象K的锁的synchronized代码块或方法,这意味着线程A同时拥有对象O和对象K的对象锁。
 
5.只有当一个线程执行完它所调用的synchronized代码块或方法时,无论是正常执行完,还是异常抛出,该线程才会释放所获取的对象锁。synchronized并不必然地保护数据。程序员应该仔细分析,识别出程序中所有的临界区,并对这些临界区施加synchronized机制。若有一处或多处遗漏,则共享变量中数据就会产生错误
 
6.临界区中的共享变量应定义为private型。否则,其他类的方法可能直接访问和操作该共享变量,这样synchronized的保护就失去了意义。所以只能通过临界区访问共享变量。故锁定的对象通常是this,即通常格式都是:synchronized(this){…}
 
7.一定要保证,所有对共享变量的访问与操作均在synchronized代码块中进行。
 
8.通常共享变量都是实例变量。若临界区中的共享变量是一个类变量,则问题复杂化了,因为类方法与实例方法均可访问类变量。而synchronized锁定的必须是对象,不能是类。建议是若临界区中的共享变量是一个类变量,则应该用类方法来访问操作该类变量。这个类方法成为一个临界区,必须将该类方法定义为synchronized方法。所有要访问该共享类变量的实例方法,都应该调用定义为synchronized的类方法进行。若实例方法一定要想在自己的代码内部,不通过synchronized的类方法访问共享类变量,则可通过synchronized(类名.class){…来访问类锁。Java中,每一个类都有一个类对象,这个类对象实际上是java.lang.Class的一个实例对象,所谓类锁就是这个类对象的一把锁。注意类锁与这个类的实例对象的对象锁虽然都是对象锁,却是不同的两把锁。所有像synchronized(类名.class()){=同步代码块} 这样锁定类对象(注意:不是锁定类的某一个实例对象),其中的synchronized代码块,都是串行执行的,访问或使用类锁要仔细考虑和权衡
 
9.当一个线程进入死亡状态,线程拥有的所有的对象锁都被释放。
3.Lock对象锁
 

Java SE5引入了java.util.concurrent.lock类库,这是解决互斥问题的第二种机制。用ReentrantLock类创建一个Lock对象,来保护临界区。用ReentrantLock保护代码块的基本结构如下。
private Lock locker =new ReentrantLock();
locker.lock(); // 加锁
try{
}finally{
  locker.unlock(); // 解锁
  }
lock()与unlock()必须配套使用。必须确保lock()对应的unlock()一定会得到执行。因此,必须把unlock()放到finally块中,确保无论是正常执行,还是异常抛出,unlock()一定会得到执行。
 
 
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之间同步。 

 
 

JAVA--对象锁的更多相关文章

  1. [转]Java 对象锁-synchronized()与线程的状态与生命周期

      线程的状态与生命周期 Java 对象锁-synchronized() ? 1 2 3 4 synchronized(someObject){   //对象锁 } 对象锁的使用说明: 1.对象锁的返 ...

  2. java 对象锁和类锁的区别(转)

    java 对象锁和类锁的区别   转自; ) ); ; ) ); 上述的代码,第一个方法时用了同步代码块的方式进行同步,传入的对象实例是this,表明是当前对象,当然,如果需要同步其他对象实例,也不可 ...

  3. Java对象锁和类锁全面解析(多线程synchronized关键字)

    最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...

  4. java 对象锁学习

    机制 锁机制是用来解决多线程共享资源时产生的冲突问题的.java 为每一个对象关联一个对象锁,通常把锁分为对象锁和类锁,他们的本质都是对象锁,只不过对象锁关联的是类的 Object 对象 (java. ...

  5. paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象)

    paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象) 1     锁的缺点 2     CAS(Compare ...

  6. java synchronized类锁,对象锁详解(转载)

    觉得还不错 留个记录,转载自http://zhh9106.iteye.com/blog/2151791 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看 ...

  7. java 哪些情况下会使对象锁释放

    Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的 ...

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

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

  9. Java虚拟机14:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  10. Java锁Synchronized,对象锁和类锁举例

    Java的锁分为对象锁和类锁. 1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内针对该对象的操作只能有一个线程得到执行.另一个线程必须 ...

随机推荐

  1. Linux网络设置高级指南

    from:http://www.oschina.net/question/23734_117144 Linux网络设置高级指南 本文面向的是被Linux复杂的有线无线网络架构弄得头昏脑胀:或者被网上半 ...

  2. Wap站总结一

    前段时间负责了公司的wap站前端工作,目前wap站的基础及较为复杂的几张页面都已经出来,现根据自己的一些经验,贴出部分心得,希望对现在或者以后可能会接触到Wap站的一些人有些帮助 一.本次WAP网站的 ...

  3. 解决php的$美元符号与Zen Coding冲突问题

    Zen Coding插件就不介绍了. 众所周知,安装了插件以后,输入$符号会被自动解析为相应的数字1.2.3... 作为一名PHP程序员,想要通过其定义一些自己常用的代码.却发现展开以后悲剧的发现$符 ...

  4. Laravel 5.1 事件、事件监听的简单应用

    ​ 有时候当我们单纯的看 Laravel 手册的时候会有一些疑惑,比如说系统服务下的授权和事件,这些功能服务的应用场景是什么,其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情,但是当我们在工作 ...

  5. 定时工作方式2实现1s定时

    定时器的几种工作方式中,除0和前面的1类似都需要初始化计数值,然后开始计数,计数溢出后,需要再次控制计数的初值,但工作模式2不同于此,工作方式2将THx和TLx分开处理,将初值存放在THx中,计数时只 ...

  6. 安装Cocoa 新的依赖管理工具Carthage

    Cocoa的依赖管理器,我们已经有了CocoaPods,非常好用,那么为什么还要创建这样一个项目呢?本文翻译自Carthage的Github的README.md,带大家来了解一下这个工具有何不同之处. ...

  7. 15 个响应式的 jQuery 图像滑块插件

    设计师和开发人员总是试图使用新技术让网站更智能,而我们发现在许多网站上 jQuery 的图像滑块插件是非常受欢迎的.本文继续介绍 15 个 jQuery 图像滑块插件以供您选择. ELASTISLID ...

  8. 【2011 Greater New York Regional 】Problem G: Rancher's Gift

    计算几何的题目,很简单: 自己随手敲了个,纪念下! #include<cstdio> #include<cmath> using namespace std; struct p ...

  9. VCC,VDD,VEE,VSS,VPP 表示的意义

    转自VCC,VDD,VEE,VSS,VPP 表示的意义 VCC,VDD,VEE,VSS,VPP 表示的意义 版本一: 简单说来,可以这样理解: 一.解释 VCC:C=circuit 表示电路的意思, ...

  10. 练习--python中的Queue与多进程(multiprocessing)

    按官方说法: This module is OBSOLETE and is only provided on PyPI to support old projects that still use i ...