技术开发 频道

JAVA线程:如何解决资源共享冲突(中)

  下面我将讲述java里如何来解决资源冲突的方案,答案很多人都知道那就是:synchronized关键字了,但是大家使用synchronnied来解决资源冲突时候,我们想过它的原理吗?java到底是运用什么样的算法解决了资源冲突了?

  其实现在所有主流程序解决线程冲突也就是共享资源竞争的问题都是采用一种叫做序列化共享资源的方案。这个方案的内容就是:在给定的时刻里只准许一个线程访问共享资源,通常这个是通过在代码前面加上一段能创建一个锁的语句,这就保证了在一定时间内只有一个线程运行这段代码。锁的作用让不同的线程之间产生相互排斥的效果,因此这种做法也叫做“互斥量”(mutex).

  Java也是采用这样的方案来解决线程冲突的问题,在java语言里,java提供了关键字synchronized,这个关键字为了防止资源冲突提供了内置支持,换句话说,当我们使用了synchronized关键字时候就告诉了java语言,你要帮我解决资源冲突的问题了。其实java语言内部,准确的说法应该是java虚拟机内部就是按照“信息量”的原理解决了这个难题,而内部的行为很像我们写的Semaphore类:有一个方法检测信号量的值,根据值的不同授予线程不同的状态(例如available方法),有一个方法会用来增加信号量的值(例如acquire方法),还有一个方法会减少信号量的值(例如release方法),最后当然也有一个监控程序了例如我们写的那样的监控框架。

  我们到底如何使用synchronized关键字的,这个问题是不是很搞笑了?我觉得有时看起来很简单的东西里面所蕴含的精髓可能相当丰富或者这个简单背后有我们难以理解的高深之处了?因此我要好好谈谈如何使用synchronized关键字的问题,当然synchronized的用法丰富多彩,我这里只讲用synchronized来解决资源共享时候的用法。这里要声明下,我对synchronized的理解还是比较有限的,而且这个关键字其他的用法我还没深入研究过,自己也写得少,假如后面的内容有些说法过于绝对或者不太正确的话还请大家多多包涵了,反正有错误希望博友们能及时指出来了。

  Synchronized的产生是为了解决线程冲突换句话说是共享资源共享的问题。从这个概念里面我们发现它包含了两个实体,一个是共享资源,一个是使用共享资源的方法。我在这里设定一个场景,把这一切的要素都放到一个类中,那么共享资源就是这个类的一个属性(不是静态的,我们谈论这个问题前提是所有的属性和方法属于对象,而不是属于类),而且一般为了保护类里面的属性,这个属性往往是私有的(private),而所有在这个类中的能访问到这个属性的方法都加synchronized,这么一看我们就明白了,synchronized在为所有方法加锁了,这种做法的结果就是当某一个线程正在使用带有synchronized关键字的方法时候,只要这个方法还在运行没有结束,其他所有该类带有synchronized的方法的线程都会被锁住。

  这里要强调一下,锁的机制一定是在对象的不同方法上的,如果是不同对象的同一个方法对于同一个资源的访问是不存在冲突的问题,换句话说线程里线程的调度是以方法为单位进行调度的,例如方法A抢占到了CPU的时间片,那么方法B就被挂起了,但是在内存中方法A应该是唯一的,因此不存在一个对象的A使用另一个对象的方法A是被挂起的,也许这个说法大家可能不太好理解,我举个例子吧,大家看下面的代码:

package cn.com.sxia;

public class SingleMethodThread{
private volatile int i = 10;
public void release(){
System.out.println("前数值是:" + i);
if (i != 0){
--i;
}else{
System.exit(0);
}
System.out.println("后数值是:" + i);
}

}
 
package cn.com.sxia;

public class SingleMethodThreadTester extends Thread {
private volatile SingleMethodThread smt;
public SingleMethodThreadTester(SingleMethodThread smt){
this.smt = smt;
start();
}

public void run(){
while(true){
smt.release();
yield();
}
}
public static void main(String[] args) {
SingleMethodThread smt = new SingleMethodThread();
new SingleMethodThreadTester(smt);
new SingleMethodThreadTester(smt);
}

}
0
相关文章