您的位置:首页 > 编程语言 > Java开发

JAVA线程基础(synchronized锁的学习)(一)

2017-04-19 23:37 190 查看
这一篇博客,是我学习完线程基础一后突然觉得要写下来记录一下,也方便自己以后查找学习!
本博客仅供参考,大神请绕路,有说的不对的地方望大家多指教!

其他不多说了,先上个例子吧!


public class study1 extends Thread{

private int count=5;

public void run() {
count--;
System.out.println(this.currentThread().getName()+":count="+count);
}

public static void main(String[] args) {

study1 s=new study1();
Thread t1=new Thread(s,"t1");
Thread t2=new Thread(s,"t2");
Thread t3=new Thread(s,"t3");
Thread t4=new Thread(s,"t4");
Thread t5=new Thread(s,"t5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}

}


上面的例子,在没有锁的情况下,五个线程都可以访问,本来我们是想要输出的是 4 3 2 1 0,这样的结果,可是事实却与我们想要的不一样,运行上面的代码输出的结果如下:

t2:count=3

t4:count=0

t5:count=0

t3:count=2

t1:count=3

这显然不是我要的结果,这时线程是不安全的,这是为什么呢,原因就是五个线程同时去操作了同一个方法,这时,显然count的值是一起使用的,这就可能会造成,第一个和第二个同时操作完成。

比如,上面的例子,我们假设只有两个线程运行,当count的值等于5时,t1和t2同时执行run方法里的代码,这时它们拿到的值都是count=5,然后两个线程t1,t2都同时对count进行减一的操作,再进行输出,这时的结果可能t1的输出结果是count=4,t2的结果是count=3;或者两个的输出结果都是count=3,因为这两个线程同时执行run方法,看哪个线程拿到了cpu的资源,(假如t1执行减一操作和输出操作的时候都拿到了cpu的资源,这时t1的输出结果就一定是4,t2的输出结果是3。)所以造成了这样的结果。

为了避免以上的情况,并拿到我们想要的结果,这时使用synchronized关键字就显得非常有必要了,如:

//synchronized加锁
public synchronized void run() {
count--;
System.out.println(this.currentThread().getName()+":count="+count);

}


我们将上面的例子的run方法来修饰,这时再去执行上面的例子结果将是:

t1:count=4

t4:count=3

t2:count=2

t5:count=1

t3:count=0

现在结果是我们想要的了,这时,线程是安全的了,因为使用synchronized关键字修饰了run方法后,就像给run方法上了一把锁,就像我们上厕所,多人去上一个厕所,先去的那个进去了把门锁住了,其他人就进不去上厕所了,必须等前面上厕所那个人出来才能下一个人去上厕所,上面的例子也是同样的道理,总之synchronized关键字就相当于一把锁一样,给run方法上了锁。因此线程是安全的。

当多个线程访问s对象的run方法时,以排队的方式进行处理(这里的排队是按照cpu分配的先后顺序而定)一个线程先要执行synchronized修饰的方法里的代码:

1.尝试获得锁

2.如果拿到锁,执行synchronized代码体内容;拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止, 而且是多个线程同时去竞争这把锁。(也就是会有锁竞争的问题)。

我们再仔细看上面的输出结果,不是按照t1,t2,t3,t4,t5的顺序来输出的,这时由于排队是按照cpu分配的先后顺序而定。由于很多个线程同时去争夺同一把锁,看谁先拿到那把锁,谁就可以先执行,上面的输出结果也就是因为这样而出现的。

关于锁竞争问题,后面有时间再解释一下,这里就不多说了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 线程