Java线程同步的使用

Synchronized,顾名思义,代表线程同步。那么,在java编程中如何使用它呢?

  我们首先来看这样一个情况:对于同一个变量synDemo,我们分别在2个不同的线程中调用synDemo.synMethord1()与synDemo.synMethord2()。

  package com.cnblogs.gpcuster;/** *  * @author Aaron.Guo * */

  public class Tester {public static void main(String[] args) {final SynDemo synDemo = new SynDemo();Thread thread1 = new Thread() {@Overridepublic void run() {// TODO Auto-generated method stub

  super.run();synDemo.synMethord1();}};Thread thread2 = new Thread() {@Overridepublic void run() {// TODO Auto-generated method stub

  super.run();synDemo.synMethord2();}};thread1.start();thread2.start();while (true) {try {Thread.sleep(1000);System.out.println("main");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  }

  我们的SynDemo是这样定义的:

  package com.cnblogs.gpcuster;/** *  * @author Aaron.Guo * */

  public  class SynDemo{public void synMethord1() {while(true) {try {Thread.sleep(1000);System.out.println("synMethord1");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  public void synMethord2() {while(true) {try {Thread.sleep(1000);System.out.println("synMethord2");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  }

  我们的SynDemo对象没有任何特殊的定义,所以运行起来以后的情况如下:

  synMethord2

  synMethord1

  main

  synMethord2

  synMethord1

  main

  synMethord2

  synMethord1

  接下来,我们给synMethord1添加上synchronized声明,运行情况还是与上次一样,因为我们只有一个线程在调用synMethord1的方法。

  我们给synMethord2也添加上synchronized声明,SynDemo对象的代码修改为:

  package com.cnblogs.gpcuster;/** *  * @author Aaron.Guo * */

  public  class SynDemo{public synchronized void synMethord1() {while(true) {try {Thread.sleep(1000);System.out.println("synMethord1");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

 public synchronized void synMethord2() {while(true) {try {Thread.sleep(1000);System.out.println("synMethord2");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  }

  这个时候,我们再运行程序,结果就不一样了:

  main

  synMethord1

  main

  synMethord1

  main

  synMethord1

  我们发现,对于SynDemo对象,只有synMethord1运行了,而synMethord2却没有运行。这是应为在方法级别的synchronized声明将lock这个类对象的当前实例。所以在synMethord1运行结束unlock之前,当前实例是无法运行synMethord2的。这种方法级别的synchronized声明和以下的做法是等同的:

  package com.cnblogs.gpcuster;/** *  * @author Aaron.Guo * */

  public class SynDemo {public void synMethord1() {synchronized (this) {while (true) {try {Thread.sleep(1000);System.out.println("synMethord1");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  }

  public synchronized void synMethord2() {synchronized (this) {while (true) {try {Thread.sleep(1000);System.out.println("synMethord2");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  }

  }

  运行程序,结果与上次相同。

  如果我们希望分别同步2个方法该如何处理?可以参考这个实现:

  package com.cnblogs.gpcuster;/** *  * @author Aaron.Guo * */

  public class SynDemo {private Object flag1 = new Object();private Object flag2 = new Object();public void synMethord1() {synchronized (flag1) {while (true) {try {Thread.sleep(1000);System.out.println("synMethord1");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  }

  public void synMethord2() {synchronized (flag2) {while (true) {try {Thread.sleep(1000);System.out.println("synMethord2");} catch (InterruptedException e) {// TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  }

  }

  运行程序,结果如我们预期:

  main

  synMethord2

  synMethord2

  main

  synMethord1

  main

  synMethord1

  synMethord2

  关于Synchronized还有一些其他的话题,如static的问题,继承的问题,与volatile搭配使用等等,在网上都有很详细的说明,这里就不重复介绍了。

添加新评论