Synchronized和java.util.concurrent.locks.Lock的区别

Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的 Condition 对象。
锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问。一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁。不过,某些锁可能允许对共享资源并发访问,如 ReadWriteLock 的读取锁。
synchronized 方法或语句的使用提供了对与每个对象相关的隐式监视器锁的访问,但却强制所有锁获取和释放均要出现在一个块结构中:当获取了多个锁时,它们必须以相反的顺序释放,且必须在与所有锁被获取时相同的词法范围内释放所有锁。
虽然 synchronized 方法和语句的范围机制使得使用监视器锁编程方便了很多,而且还帮助避免了很多涉及到锁的常见编程错误,但有时也需要以更为灵活的方式使用锁。例如,某些遍历并发访问的数据结果的算法要求使用 "hand-over-hand" 或 "chain locking":获取节点 A 的锁,然后再获取节点 B 的锁,然后释放 A 并获取 C,然后释放 B 并获取 D,依此类推。Lock 接口的实现允许锁在不同的作用范围内获取和释放,并允许以任何顺序获取和释放多个锁,从而支持使用这种技术。
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 做的那样。
Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。
 
主要相同点:Lock能完成Synchronized所实现的所有功能。

主要不同点:Lock有比Synchronized更精确的县城予以和更好的性能。Synchronized会自动释放锁,但是Lock一定要求程序员手工释放,并且必须在finally从句中释放。
synchronized 修饰方法时 表示同一个对象在不同的线程中 表现为同步队列
如果实例化不同的对象 那么synchronized就不会出现同步效果了。
 
 
1.对象的锁 
所有对象都自动含有单一的锁。 
JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。 
只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。 
每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。 
2.synchronized同步块 
2.1同步到单一对象锁 
当使用同步块时,如果方法下的同步块都同步到一个对象上的锁,则所有的任务(线程)只能互斥的进入这些同步块。 
Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,虽然这些同步块处在不同的方法中,但由于是同步到同一个对象(当前对象 synchronized (this)),所以对它们的方法依然是互斥的。 
 
package com.org.thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 *@DEMO:JavaSE
 *@Author:jilongliang
 *@Date:2013-3-21
 */
public class Locker {
   public static void main(String[] args) {
        Resources1 res = new Resources1();
        Pro p = new Pro(res);
        Customer1 c = new Customer1(res);
        new Thread(p).start();
        new Thread(c).start();
    }
}
class Pro implements Runnable {
    Resources1 resource;
    Pro(Resources1 res) {
    this.resource = res;
 }
@Override
public void run() {
  while (true) {
  try {
     resource.set("商品");
  } catch (InterruptedException e) {
     e.printStackTrace();
   }
  }
}
}
class Customer1 implements Runnable {
    Resources1 res;
    Customer1(Resources1 res) {
    this.res = res;
}
@Override
public void run() {
  while (true) {
    synchronized (res) {
    try {
      res.out();
   } catch (InterruptedException e) {
     e.printStackTrace();
 }
}
}
}
}
/**
 * wait notify notifyAll 都在使用在同步中,因为要对持有监视器(锁)的线程 操作 所以要使用在同步中,因为只有同步才具有锁
 * 为什么这些操作线程的方法要定义Object类中?
 * 因为这些方法在操作同步中线程时,都必须要标识他们所操作线程只有的锁
 * 只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒 不可以对不同锁中的线程进行唤醒
 * 也就是说,等待和唤醒必须是同一个锁 而锁可以是任意对象,所以可以被任意对象调用的方法定义了
 * Object类中
 */
class Resources1 {
    private String name;
     private int count = 1;
     private boolean flag = false;
     private Lock lock = new ReentrantLock();
     private Condition condition_pro = lock.newCondition();
     private Condition condition_con = lock.newCondition();
     public void set(String name) throws InterruptedException {
     lock.lock();
     try {
          while (flag)
          // this.wait();
          condition_pro.await();// 等待
          this.name = name + "=生产数:" + count++;
          System.out.println(Thread.currentThread().getName() + "生产者:"
          + this.name);
          flag = true;
          condition_con.signalAll();
          // this.notifyAll();
          } finally {
               lock.unlock();
          }
     }
     public void out() throws InterruptedException {
          lock.lock();
          try {
          while (!flag)
               // this.wait();
               condition_con.await();
               System.out.println(Thread.currentThread().getName()
               + "消费者===========" + this.name);
               flag = false;
               condition_pro.signalAll();
               // this.notifyAll();
               } finally {
               lock.unlock();
          }
          }
}


转载于:https://my.oschina.net/u/195065/blog/191816

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值