多线程编程中,最关键、最关心的问题应该就是同步问题,这是一个难点,也是核心。从
jdk 最 早 的 版 本 的 synchronized 、 volatile , 到 jdk 1.5 中 提 供 的
java.util.concurrent.locks
包
中
的
Lock
接
口
(
实
现
有
ReadLock,WriteLock,ReentrantLock),多线程的实现也是一步步走向成熟化。
同步,它是通过什么机制来控制的呢?第一反应就是锁,这个在学习操作系统与数据
库的时候,应该都已经接触到了。在 Java 的多线程程序中,当多个程序竞争同一个资源
时,为了防止资源的腐蚀,给第一个访问资源的线程分配一个对象锁,而后来者需要等
待这个对象锁的释放。
是的,Java 线程的同步,最关心的是共享资源的使用。
先来了解一些有哪些线程的共享资源:
从 JVM 中了解有哪些线程共享的数据是需要进行协调:一个是保存在堆中的实例变
量;保存在方法区的类变量。
而在 Java 虚拟机加载类的时候,每个对象或类都会与一个监视器相关联,用来保护
对象的实例变量或类变量;当然,如果对象没有实例变量,或类没有变量,监视器就什么
也不监视了。
为了实现上面的说的监视器的互斥性,虚拟机为每一个对象或类都关联了一个锁(也
叫隐形锁),这里说明一下,类锁也是通过对象锁来实现的,因为在类加载的时候,JVM
会为每一个类创建一个 java.lang.Class 的一个实例;所以当锁对对象的时候,也就锁住
这个类的类对象。
另外,一个线程是可以对一个对象进行多次上锁,也就对应着多次释放 ;它是通过
JVM 为每个对象锁提供的 lock 计算器,上一次锁,就加 1,对应的减 1,当计算器的值
为 0 时,就释放。这个对象锁是 JVM 内部的监视器使用的,也是由 JVM 自动生成的,所
有程序猿就不用自己动手来加了。
介绍完 java 的同步原理后,我们进入正题,先来说说 synchronized 的使用。
先来运行一个例子试试。
1.package thread_test;
2.
3./**
4. * 测试扩展 Thread
类实现的多线程程序
5. *
6. * @author ciding
7. * @createTime Dec 7, 2011 9:37:25 AM
8. *
9. */
10.public class TestThread extends Thread{
11. private int threadnum;
12.
13. public TestThread(int threadnum) {
14. this.threadnum = threadnum;
15. }
16.
17. @Override
18. public synchronized void run() {
19. for(int i = 0;i<1000;i++){