Java 线程同步 synchronized

先来看一个不带线程同步的例子,这个例子很简单,只是让两个线程输出同样的内容,并不做其他的事,所以,线程同步在这里体现的并不明显。

import java.util.Date; public class ThreadTest extends Thread{ int pauseTime; String name; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ThreadTest tT1 = new ThreadTest(1000, "Thread1"); tT1.start(); ThreadTest tT2 = new ThreadTest(3000, "Thread2"); tT2.start(); } public ThreadTest(int pauseTime , String name){ this.pauseTime = pauseTime; this.name = name; } @Override public void run() { // TODO Auto-generated method stub super.run(); while(true){ try { System.out.println(name + ":" + new Date(System.currentTimeMillis())); Thread.sleep(pauseTime); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } } 

在来看一个多线程售票的问题,这个例子中体现线程同步的重要性,不保证这一点将会导致错误的执行结果

class TicketSouce implements Runnable { //票的总数 private int ticket=10; public void run() { for(int i=1;i<50;i++) { if(ticket>0) { //休眠1s秒中,为了使效果更明显,否则可能出不了效果 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票"); } } } } public class Test { public static void main(String args[]) { TicketSouce mt=new TicketSouce(); //基于火车票创建三个窗口 new Thread(mt,"1").start(); new Thread(mt,"2").start(); new Thread(mt,"3").start(); } } 

输出结果如下图所示:

Java 线程同步 synchronized_第1张图片


可以看到,输出的结果并不是我们想要的,所以,需要线程同步的支持


当一个线程要使用火车票这个资源时,我们就交给它一把锁,等它把事情做完后在把锁给另一个要用这个资源的线程。这样就不会出现上述情况。 实现这个锁的功能就需要用到synchronized这个关键字。

synchronized这个关键字有两种用法1、放方法名前形成同步方法;2、放在块前构成同步块。


我们首先用第一种方法实现售票的功能:

代码如下:

class TicketSouce implements Runnable { //票的总数 private int ticket=10; public void run() { for(int i=1;i<50;i++) { try { //休眠1s秒中,为了使效果更明显,否则可能出不了效果 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.sale(); } } public synchronized void sale() { if(ticket>0) { System.out.println(Thread.currentThread().getName()+"号窗口卖出"+this.ticket--+"号票"); } } } public class Test { public static void main(String args[]) { TicketSouce mt=new TicketSouce(); //基于火车票创建三个窗口 new Thread(mt,"a").start(); new Thread(mt,"b").start(); new Thread(mt,"c").start(); } } 

第二种同步的方法如下:

class TicketSouce implements Runnable { //票的总数 private int ticket=10; public void run() { for(int i=1;i<50;i++) { synchronized(this){ if(ticket>0) { //休眠1s秒中,为了使效果更明显,否则可能出不了效果 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+ "号窗口卖出" + this.ticket-- + "号票"); } } } } } public class ThreadTest { //主线程 public static void main(String args[]) { TicketSouce mt=new TicketSouce(); //建立三个线程,同步操作 new Thread(mt,"1").start(); new Thread(mt,"2").start(); new Thread(mt,"3").start(); } } 

两段程序输出的结果如下所示:

Java 线程同步 synchronized_第2张图片


可以看到,两段程序都有正确的输出。


注意:同步关键字需要放对地方,否则可能出现不可预料的结果。

你可能感兴趣的:(java,多线程,线程,类,同步)