关键段(critical section) 用关键字synchronized声明
在多线程程序中,关键段具有原子性,关键段没有执行完即使该线程时间片完也不会切换到下个线程
运行关键段时,线程需要获得对象的key,线程获得key后就锁住对象资源,知道关键段运行完毕才会释放key
就像ASP.NET中的Lock();和Unlock();一样 相当于操作系统和数据库原理的加锁解锁的概念
声明方法:
synchronized (object) {
//Critical Section
}
另外一种声明方法:
synchronized void function() {
//Critical Section
} //相当于 synchronized (this) {}
其中Object是关键段需要Key的拥有对象,也就是说运行以上代码时,线程先要获得object对象的key,如果key已经别的线程拿走 则等待拥有key的线程运行完关键段后释放该key
应注意:
1。每个对象只有一个Key
2。为执行syncronized()块,线程需要对象的key,一旦获得key,对象不再拥有key
3。若线程执行syncronized()时,key不在对象中,线程Stall,一直到key还于对象,才能被线程拿到
程序示例:
private int num=0;
public static void main(String[] args) ...{
SynThread s1=new SynThread();
Thread t1=new Thread(s1);
Thread t2=new Thread(s1);
t1.start();
t2.start();
}
public void run() ...{
while(true) ...{
synchronized (this) ...{
int temp=this.num+1;
try ...{
Thread.sleep(1000);
}
catch(InterruptedException e) ...{
System.out.print("Catch a InterruptedException!");
}
this.num=temp;
System.out.println(this.num);
}
}
}
}
运行结果:
1
2
3
4
5
6
7
... ...
如果没有使用syncronized关键字,结果将不可预料,因为这取决于每个线程划分的时间片和程序段运行的时间。程序段执行一半可能会被另一线程打断并重新给num赋值,对象的共有资源num可能会被混乱地赋值。
可能会是
1
1
2
2
3
3
... ...