人生没有彩排,每天都是现场直播!

平时做项目的时候,或多说少的涉及到多线程的环境,那么如何在多线程中保证线程的安全,这是我们必须要考虑的,尤其是,银行之间的转账和取钱操作之间,必须要保证,每个时刻,只能有一个线程来操纵方法。而在java中为我们提供了synchronized关键字。

和普通的房间(普通的方法),然而房子的钥匙就放置在大门口,因此当第一个人来的时候,就要先去拿钥匙,如果有钥匙的话,就可以拿着钥匙进入房间去,用完后需要归还,,哪怕还需要进入,也需要把钥匙归还后再去取钥匙。当然如果有很多人都在等钥匙的话,那么钥匙归谁呢,这就看JVM如何来分配资源调配了。不确定的。

这里需要注意的是,为了保证房子里面上锁的房间的安全,正如上图所示,必须要保证上锁的房间的钥匙是唯一的。

在实际中,锁可以放置在方法上,也可以作为一个单独语句块来上锁,换句话说我们也可以把一个房间里面的一块区域来上锁。(必须要保证锁是唯一的)

下面来看几个例子,通过例子来深入的理解一下synchronized关键字。

<span style="font-family:Comic Sans MS;font-size:18px;">package com.test;public class TraditionThread {public static void main(String[] args) {final Outputer outputer = new Outputer();new Thread(new Runnable(){@Overridepublic void run() {while(true){try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}outputer.output("哈哈哈");}}}).start();new Thread(new Runnable(){@Overridepublic void run() {while(true){try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}outputer.output2("大大大大阿达");}}}).start();}static class Outputer {public void output(String name) {//如果有很多需要锁住的方法的话,则也必须保证只有一把钥匙,这个意思就是锁住的方法的钥匙都是一样的//锁一定要是同一个对象才可以//这样的话就保证了只有一把钥匙String xxxString="";int len = name.length();//钥匙不一样,所以都可以打开这扇门,如果要保持线程唯一的话,只能有一把钥匙synchronized (xxxString) {for (int i = 0; i < len; i++) {System.out.print(name.charAt(i));}System.out.println();}}//而同步方法则是this对象public synchronized void output2(String name) {int len = name.length();for (int i = 0; i < len; i++) {System.out.print(name.charAt(i));}System.out.println();}}}</span>

可以看到在main方法中,同一个对象分别在两个线程中调用两个加锁的方法,这时候为了保证线程中的安全,也就是上面提到的,我在进入一个加锁房间的时候,别人是不能进入的,为了保证能够实现这种效果,因此每个房间的锁都是一样的,可以看上面的程序第一个房间的锁的钥匙是一个xxxString类型的对象,而第二个房间的锁的钥匙是当前的类,也就是this,因此房间的钥匙是不一样的,所以保证不了线程的安全,需要要修改的话,只需要将第一个房间的钥匙修改为this,即synchronized (this) {}。

变动一

如果我们这时候把main方法修改一下的话,让两个对象分别在两个线程中调用的话,会是怎样的效果呢?大家可想而知,这样的话,相当于我有两套同样的房子,那么这两个对象都可以拿到各自的钥匙,都可以进入,因此还是保证不了线程的安全

<span style="font-family:Comic Sans MS;font-size:18px;">public class TraditionThread {public static void main(String[] args) {final Outputer outputer = new Outputer();new Thread(new Runnable(){@Overridepublic void run() {while(true){try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}outputer.output("哈哈哈");}}}).start();new Thread(new Runnable(){@Overridepublic void run() {while(true){try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}//两个对象,更加保证不了线程的安全new Outputer().output2("大大大大阿达");}}}).start();}</span>

变动二

此时,我们再添加另外一间加锁的房间,所以修改后的代码如下

<span style="font-family:Comic Sans MS;font-size:18px;">//加锁的房子static class Outputer {public void output(String name) {//如果有很多需要锁住的方法的话,则也必须保证只有一把钥匙,这个意思就是锁住的方法的钥匙都是一样的//锁一定要是同一个对象才可以//这样的话就保证了只有一把钥匙String xxxString="";int len = name.length();//钥匙不一样,所以都可以打开这扇门,如果要保持线程唯一的话,只能有一把钥匙synchronized (this) {for (int i = 0; i < len; i++) {System.out.print(name.charAt(i));}System.out.println();}}//而同步方法则是this对象//加锁的房间public synchronized void output2(String name) {int len = name.length();for (int i = 0; i < len; i++) {System.out.print(name.charAt(i));}System.out.println();}//加锁的房间public static synchronized void output3(String name){int len = name.length();for(int i=0;i<len;i++){System.out.print(name.charAt(i));}System.out.println();}}</span>其实生命无论长短,只要我们能努力绽放出生命的光彩,便会拥有精彩的人生。

人生没有彩排,每天都是现场直播!

相关文章:

你感兴趣的文章:

标签云: