Java中的同步与互斥机制--synchornized学习

原创 2007年10月11日 17:53:00
    Java关键字synchronizedJava 语言提供的对多线程和同步的一种机制。synchronized可以作为函数的修饰符,也可作为函数内的语句。它可以作用于instance变量,对象引用(object reference),static函数和类名称字面常量(class literals)。

  下面介绍一下synchronized的关键字的使用方法:

一、synchronized作函数修饰符

public synchronized void fun()
{
    ……..
}
    fun()就是一个同步方法,此时synchronized关键字锁定的是调用这个同步方法的对象。假设有p1p2是同一个类的两个对象,p1在不同的线程中运行会对fun()产生互斥和同步的效果;但是p2对象和p1对象互相不会对fun()产生同步和互斥作用(当然,不同线程中的p2对象的fun()还是有同步和互斥)。

  对于非static的情况,synchronized是对象级别的,其实质是将synchronized作用于对象引用(object reference)上,即拿到p1对象锁的线程,对p1fun()方法有同步互斥作用,不同的对象之间坚持“和平共处”。因此,上面的代码等同于:

public void fun()
{
  synchronized(
this)  // this指的是调用这个方法的对象
  {
      ……
  }
}

二、synchronized同步程序块

public void fun_1(someObject obj)
{
  
synchronized(obj)
  {
      ……
  }
}

  上面代码中,锁住的是obj对象(正如前面说的,对于非static的情况,sysnchronized是对象级别的),谁拿到这个锁,谁就可运行obj控制的那段代码。通常情况,如果我们知道对用哪个对象作为锁时,就可以像上面的代码块一样使用synchronized。假如没有明确的对象作为锁,程序员又希望同步一段代码块,就可以使用下面的trick

class Test implements Runnable
{
  
private byte[] lock = new byte[0];  // 定一个instance变量
  public void fun_2()
  {
      
synchronized(lock)
      {
          ……
      }
  }
}

  在上面的代码示例中,定义了一个特殊的instance变量作为锁,这个instance变量必须是一个对象。定义lock为长度为0的数组对象是最佳方案。在编译后的字节码中,生成长度为0byte[]只需要三条操作码。假如我们用所有类的超类Object来作锁,需要生成七条操作码。

[注意:]如果需要定义特殊的instance变量作为锁,最好将其定义为private的,同时定义其get()方法(如果使用自己定义的类的对象作为锁)。如果变量是public的,其他类的对象可以得到这个锁的控制权,并修改这个锁。这是非常不安全的。

[注意:] 如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。这个时候就需要将get方法也加上synchronized同步,并且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了。

三、synchronized修饰static方法

    synchronized静态(static)方法的用法如下面代码示例:

public static synchronized void fun_3()
{
    ……
}

  如果方法用static修饰,synchronized的作用范围就是class一级的,它对类的所有对象起作用。像第一点中的fun()方法,如果是static的,那么synchronizedp1对象和p2对象都起到同步互斥的作用。

  其实说白了,对于staticsynchronize也可以理解为对象级别的(hoho!是不是有点糊涂了? ^_^),因此下面代码可以达到同样效果:

class XX
{
    
public static void fun_4()
    {
    
synchronized(XX.class)
    {
        ……
    }
    }
}

  请注意,XX.class也是一个对象,类型是Class,在一个ClassLoader里,它是唯一的。因此,我在前面说,也理解它是对象级别的。

  最后简单总结一下:

(1)     通常把synchronized关键字的作用范围划分为类的范围和对象的范围两种,不过偶个人理解的是,既然取得的锁都是对象(参考第三点),也可以认为synchronized关键字都作用于对象。

(2)     synchronized关键字是不能继承的,即,父类的synchronized方法在子类中不是synchronized,必须要重新的显式的声明为synchronized才行。

(3)     实现同步需要很大的系统开销,导致延迟等待,甚至可能造成死锁,所以在非多线程情况下不要使用。

Java中多线程互斥访问的实现

1、没有实现线程互斥的函数      1.1  没有实现多线程互斥访问的函数 [java] view plain copy  print? static class Outpu...
  • zbw18297786698
  • zbw18297786698
  • 2016-12-02 15:48:56
  • 1408

Java--线程的互斥实现(两种方法)

我们是利用synchronized的两种方法:声明一条语句或声明一个方法方法——:同步语句,使用synchronized(对象)后面接语句即可方法二 同步方法,使用synchronized(this)...
  • SHYLOGO
  • SHYLOGO
  • 2017-05-28 22:42:23
  • 938

java同步和互斥

来源:http://blog.csdn.net/lazy_tiger/article/details/1820582   Java关键字synchronized是Java 语言提供的对多线程和同...
  • chunqiuwei
  • chunqiuwei
  • 2012-05-31 22:38:33
  • 6365

Java多线程编程--(3)线程互斥、同步的理解

多线程并行编程中,线程间同步与互斥是一个很有技巧的也很容易出错的地方。 线程间互斥应对的是这种场景:多个线程操作同一个资源(即某个对象),为保证线程在对资源的状态(即对象的成员变量)进行一些非原子性...
  • DrifterJ
  • DrifterJ
  • 2012-07-24 23:24:41
  • 14819

Java保证两个方法互斥的方式,多线程同步

1、当需要保证多个方法的互斥,需要保证有一个共同的标准作为基准,这个基准就是一个锁。当2个以上的方法需要保证互斥,需要他们获取相同的锁,当一个方法拥有锁之后,其他的方法不能够获得锁,达到互斥的作用。 ...
  • zsf5201314z
  • zsf5201314z
  • 2017-06-22 10:55:38
  • 767

Java高效并发之乐观锁悲观锁、(互斥同步、非互斥同步)

乐观锁和悲观锁 首先我们理解下两种不同思路的锁,乐观锁和悲观锁。 这两种锁机制,是在多用户环境并发控制的两种所机制。下面看百度百科对乐观锁和悲观锁两种锁机制的定义: 乐观锁( O...
  • truelove12358
  • truelove12358
  • 2017-02-10 10:48:23
  • 36057

java 互斥与同步的区别与联系

相交进程之间的关系主要有两种,同步与互斥。所谓互斥,是指散步在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它 们之中的任一程序片段,只能等到该进程运行完这个程序片段...
  • wuyulunbi12580
  • wuyulunbi12580
  • 2012-11-01 21:20:17
  • 396

Java中的ReentrantLock和synchronized两种锁定机制的对比

原文:http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html 多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新...
  • fw0124
  • fw0124
  • 2011-08-09 15:03:01
  • 216282

Java中Synchronized的用法

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代...
  • luoweifu
  • luoweifu
  • 2015-06-24 00:25:01
  • 288152

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

在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。Synchronized既可以对代码块使用,也可以加在整...
  • xiao__gui
  • xiao__gui
  • 2012-11-15 22:22:00
  • 71947
收藏助手
不良信息举报
您举报文章:Java中的同步与互斥机制--synchornized学习
举报原因:
原因补充:

(最多只允许输入30个字)