`

java多线程同步

阅读更多

多线程的线程同步机制实际上是靠锁的概念来控制的。那么在Java程序当中,锁是如何体现的呢?


让我们从JVM的角度来看看锁这个概念:

在Java程序运行时环境中,JVM需要对两类线程共享的数据进行协调:
1)保存在堆中的实例变量
2)保存在方法区中的类变量(静态变量

 

 

这两类数据是被所有线程共享的。
程序不需要协调保存在Java 栈当中的数据。因为这些数据是属于拥有该栈的线程所私有的。)

在java虚拟机中,每个对象和类在逻辑上都是和一个监视器相关联的。
对于对象来说,相关联的监视器保护对象的实例变量。

对于类来说,监视器保护类的类变量。

(如果一个对象没有实例变量,或者一个类没有变量,相关联的监视器就什么也不监视。)
为了实现监视器的排他性监视能力,java虚拟机为每一个对象和类都关联一个锁。代表任何时候只允许一个线程拥有的特权。线程访问实例变量或者类变量不需锁。

但是如果线程获取了锁,那么在它释放这个锁之前,就没有其他线程可以获取同样数据的锁了。(锁住一个对象就是获取对象相关联的监视器

类锁实际上用对象锁来实现。当虚拟机装载一个class文件的时候,它就会创建一个java.lang.Class类的实例。当锁住一个对象的时候,实际上锁住的是那个类的Class对象。

一个线程可以多次对同一个对象上锁。对于每一个对象,java虚拟机维护一个加锁计数器,线程每获得一次该对象,计数器就加1,每释放一次,计数器就减 1,当计数器值为0时,锁就被完全释放了。

java编程人员不需要自己动手加锁,对象锁是java虚拟机内部使用的。

在java程序中,只需要使用synchronized块或者synchronized方法就可以标志一个监视区域。当每次进入一个监视区域时,java 虚拟机都会自动锁上对象或者类。

 

 

  public static synchronized void abc(int threadNo) {
       for(int i = 1; i < 10000; i++) {
               System.out.println("No." + threadNo + ":" + i);
      }
  }

 

@Override
 public void run() {
  synchronized (lock) {
   for(int i =0 ;i<1000;i++)
    System.out.println(i);
  }
     abc(2) 

}
 
 public static void main(String[] args) {
  String lock="lock";
  for(int i=0; i<1000;i++){
   new ThreadTest(lock).start();
  }
 }
通过锁定,“lock”这个共享数据,来实现同步

 

1、这些线程的lock变量实际上指向的是堆内存中的同一个区域,即存放main函数中的lock变量的区域。

2、对于同步静态方法,对象锁就是该静态放发所在的类的Class实例,由于在JVM中,所有被加载的类都有唯一的,具体到本例,就是唯一的 ThreadTest.class对象。不管我们创建了该类的多少实例,但是它的类实例仍然是一个!

静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。

 

http://ajava.org/course/java/17925.html

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics