`
javaeyetodj
  • 浏览: 431506 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java锁机制Synchronized方法简介《一》

阅读更多
转自http://webservices.ctocio.com.cn/java/398/9398398_3.shtml
打个比方:一个object就像一个大房子,大门永远打开。房子里有很多房间(也就是方法)。这些房间有上锁的(synchronized方法), 和不上锁之分(普通方法)。房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间。另外我把所有想调用该对象方法的线程比喻成想进入这房子某个 房间的人。所有的东西就这么多了,下面我们看看这些东西之间如何作用的。

  在此我们先来明确一下我们的前提条件。该对象至少有一个synchronized方法,否则这个key还有啥意义。当然也就不会有我们的这个主题了。

  一个人想进入某间上了锁的房间,他来到房子门口,看见钥匙在那儿(说明暂时还没有其他人要使用上锁的房间)。于是他走上去拿到了钥匙,并且按照自己 的计划使用那些房间。注意一点,他每次使用完一次上锁的房间后会马上把钥匙还回去。即使他要连续使用两间上锁的房间,中间他也要把钥匙还回去,再取回来。

  因此,普通情况下钥匙的使用原则是:“随用随借,用完即还。”

  这时其他人可以不受限制的使用那些不上锁的房间,一个人用一间可以,两个人用一间也可以,没限制。但是如果当某个人想要进入上锁的房间,他就要跑到大门口去看看了。有钥匙当然拿了就走,没有的话,就只能等了。

  要是很多人在等这把钥匙,等钥匙还回来以后,谁会优先得到钥匙?Not guaranteed。象前面例子里那个想连续使用两个上锁房间的家伙,他中间还钥匙的时候如果还有其他人在等钥匙,那么没有任何保证这家伙能再次拿到。 (JAVA规范在很多地方都明确说明不保证,象Thread.sleep()休息后多久会返回运行,相同优先权的线程那个首先被执行,当要访问对象的锁被 释放后处于等待池的多个线程哪个会优先得到,等等。我想最终的决定权是在JVM,之所以不保证,就是因为JVM在做出上述决定的时候,绝不是简简单单根据 一个条件来做出判断,而是根据很多条。而由于判断条件太多,如果说出来可能会影响JAVA的推广,也可能是因为知识产权保护的原因吧。SUN给了个不保证 就混过去了。无可厚非。但我相信这些不确定,并非完全不确定。因为计算机这东西本身就是按指令运行的。即使看起来很随机的现象,其实都是有规律可寻。学过 计算机的都知道,计算机里随机数的学名是伪随机数,是人运用一定的方法写出来的,看上去随机罢了。另外,或许是因为要想弄的确定太费事,也没多大意义,所 以不确定就不确定了吧。)

  再来看看同步代码块。和同步方法有小小的不同。

  1.从尺寸上讲,同步代码块比同步方法小。你可以把同步代码块看成是没上锁房间里的一块用带锁的屏风隔开的空间。

  2.同步代码块还可以人为的指定获得某个其它对象的key。就像是指定用哪一把钥匙才能开这个屏风的锁,你可以用本房的钥匙;你也可以指定用另一个房子的钥匙才能开,这样的话,你要跑到另一栋房子那儿把那个钥匙拿来,并用那个房子的钥匙来打开这个房子的带锁的屏风。

  记住你获得的那另一栋房子的钥匙,并不影响其他人进入那栋房子没有锁的房间。

  为什么要使用同步代码块呢?我想应该是这样的:首先对程序来讲同步的部分很影响运行效率,而一个方法通常是先创建一些局部变量,再对这些变量做一些 操作,如运算,显示等等;而同步所覆盖的代码越多,对效率的影响就越严重。因此我们通常尽量缩小其影响范围。如何做?同步代码块。我们只把一个方法中该同 步的地方同步,比如运算。

  另外,同步代码块可以指定钥匙这一特点有个额外的好处,是可以在一定时期内霸占某个对象的key。还记得前面说过普通情况下钥匙的使用原则吗。现在不是普通情况了。你所取得的那把钥匙不是永远不还,而是在退出同步代码块时才还。

  还用前面那个想连续用两个上锁房间的家伙打比方。怎样才能在用完一间以后,继续使用另一间呢。用同步代码块吧。先创建另外一个线程,做一个同步代码 块,把那个代码块的锁指向这个房子的钥匙。然后启动那个线程。只要你能在进入那个代码块时抓到这房子的钥匙,你就可以一直保留到退出那个代码块。也就是说 你甚至可以对本房内所有上锁的房间遍历,甚至再sleep(10*60*1000),而房门口却还有1000个线程在等这把钥匙呢。很过瘾吧。

  在此对sleep()方法和钥匙的关联性讲一下。一个线程在拿到key后,且没有完成同步的内容时,如果被强制sleep()了,那key还一直在 它那儿。直到它再次运行,做完所有同步内容,才会归还key。记住,那家伙只是干活干累了,去休息一下,他并没干完他要干的事。为了避免别人进入那个房间 把里面搞的一团糟,即使在睡觉的时候他也要把那唯一的钥匙戴在身上。

  最后,也许有人会问,为什么要一把钥匙通开,而不是一个钥匙一个门呢?我想这纯粹是因为复杂性问题。一个钥匙一个门当然更安全,但是会牵扯好多问题。钥匙的产生,保管,获得,归还等等。其复杂性有可能随同步方法的增加呈几何级数增加,严重影响效率。这也算是一个权衡的问题吧。为了增加一点点安全性,导致效率大大降低,是多么不可取啊。

  1、synchronized关键字的作用域有二种:

  1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;

  2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

  2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

  3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;

  synchronized的一个简单例子


  public class TextThread
  {
  /**
  * @param args
  */
  public static void main(String[] args)
  {
  // TODO 自动生成方法存根
  TxtThread tt = new TxtThread();
  new Thread(tt).start();
  new Thread(tt).start();
  new Thread(tt).start();
  new Thread(tt).start();
  }
  }
  class TxtThread implements Runnable
  {
  int num = 100;
  String str = new String();
  public void run()
  {
  while (true)
  {
  synchronized(str)
  {
  if (num>0)
  {
  try
  {
  Thread.sleep(10);
  }
  catch(Exception e)
  {
  e.getMessage();
  }
  System.out.println(Thread.currentThread().getName()+ "this is "+ num--);
  }
  }
  }
  }
  }

分享到:
评论

相关推荐

    java锁机制Synchronizedjava锁机制Synchronized

    Java 锁机制 Synchronized 是 Java 语言中的一种同步机制,用于解决多线程并发访问共享资源时可能出现的一些问题。 Java 锁机制 Synchronized 的概念 在 Java 中,每个对象都可以被看作是一个大房子,其中有多个...

    java锁机制Synchronized.pdf

    java锁机制Synchronized.pdf

    java锁机制Synchronized[归纳].pdf

    java锁机制Synchronized[归纳].pdf

    java锁机制Synchronized参考.pdf

    java锁机制Synchronized参考.pdf

    Java锁机制详解.pdf

    Java锁机制的发展历经了多个版本的改进,尤其是Java 5.0引入的显示锁(Explicit Locks),提供了一系列比内置锁(synchronized)更灵活的同步手段。 在Java中,内置锁是通过synchronized关键字实现的,而显示锁则是...

    java锁机制详解.pdf

    Java锁机制是多线程编程中的关键概念,用于控制对共享资源的并发访问。在Java中,主要的锁机制包括`synchronized`关键字和`Lock`接口(如`ReentrantLock`)。下面将详细讲解这两种锁机制及其应用。 1. `...

    java锁详解.pdf

    5. 重量级锁:重量级锁是 synchronized 锁的一种实现方式,使用互斥量来实现锁机制。 二、ReentrantLock 锁 1. 锁的原理:ReentrantLock 锁是基于 AQS(AbstractQueuedSynchronizer)机制来实现的。 2. 锁的分类:...

    面向Java锁机制的字节码自动重构框架.zip

    总的来说,Java锁机制是保证多线程安全的关键,而面向Java锁机制的字节码自动重构框架则是提高并发性能的一种高级技术。它通过深入字节码层面,提供了一种自动优化锁使用的方式,帮助开发者更有效地管理和优化并发...

    java的线程同步机制synchronized关键字的理解_.docx

    1. 无论 synchronized 关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁。 2. 每个对象只有一个锁(lock)与之相关联。 3. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁...

    java 多线程synchronized互斥锁demo

    Java的`synchronized`关键字提供了解决方案,通过互斥锁机制,使得在同一时刻,只有一个线程能够获得锁并执行特定的代码,其他试图访问的线程则必须等待。 `synchronized`关键字有两种主要的使用方式: 1. **同步...

    彻底理解Java中的各种锁.pdf

    通过以上对Java锁机制的详细介绍,可以看出Java在并发控制方面具有丰富的工具和策略,它们能够帮助开发者在多线程编程中处理好资源竞争和线程协作的问题,从而编写出高效且线程安全的应用程序。

    Java的锁机制的学习和使用

    #### 一、Java锁机制概览 Java中的锁机制主要用于解决多线程环境下的资源竞争问题。在并发编程中,为了保证数据一致性与正确性,通常需要采用各种锁来控制对共享资源的访问。Java语言提供了多种锁机制,包括`...

    Java 同步锁(synchronized)详解及实例

    Java中的同步锁,即`synchronized`关键字,是Java多线程编程中用于解决并发问题的重要机制。它确保了对共享资源的互斥访问,防止数据的不一致性。当我们有多线程环境并涉及到共享数据时,可能会出现竞态条件,就像...

    java同步synchronized关键字用法示例

    `synchronized`关键字的工作原理基于Java内存模型(JMM)中的锁机制。当一个线程进入同步代码块后,会获取到监视器对象的锁,其他试图进入的线程会被阻塞,直到持有锁的线程退出同步代码块并释放锁。 **3. volatile...

    [JAVA][synchronized的使用]

    `synchronized`关键字在Java中提供了互斥访问,也就是说,当一个线程进入一个对象的`synchronized`代码块或方法时,其他线程对这个对象的`synchronized`代码块或方法的访问将会被阻塞,直到当前线程执行完毕并释放锁...

Global site tag (gtag.js) - Google Analytics