6、线程的同步

来源:互联网 发布:linux on android 编辑:程序博客网 时间:2024/06/06 05:57

多个线程同时处理同一资源的线程不安全实例,线程1和2同时操作ticket

package com.chocus.demo1;public class ThreadDemo6 {  public static void main(String[] args) {    MyRunnable6 mr = new MyRunnable6();    Thread t = new Thread(mr);    Thread t2 = new Thread(mr);    t.start();    t2.start();  }}class MyRunnable6 implements Runnable {  private int ticket = 10;  @Override  public void run() {    for (int i = 0; i < 20; i++) {      if (ticket > 0) {        ticket--;        try {          Thread.sleep(300);        } catch (InterruptedException e) {          // TODO Auto-generated catch block          e.printStackTrace();        }        System.out.println("剩余票数" + ticket + "张");      }    }  }}

结果

剩余票数8张剩余票数7张剩余票数6张剩余票数6张剩余票数4张剩余票数4张剩余票数2张剩余票数1张剩余票数0张剩余票数0张

当线程sleep时,会交出执行权,但不会释放锁。

使用同步代码块:

package com.chocus.demo1;public class ThreadDemo6 {  public static void main(String[] args) {    MyRunnable6 mr = new MyRunnable6();    Thread t = new Thread(mr);    Thread t2 = new Thread(mr);    t.start();    t2.start();  }}class MyRunnable6 implements Runnable {  private int ticket = 10;  @Override  public void run() {    for (int i = 0; i < 20; i++) {      if (ticket > 0) {        synchronized (this) {          ticket--;          try {            Thread.sleep(300);          } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();          }          System.out.println("剩余票数" + ticket + "张");        }      }    }  }}

结果

剩余票数9张剩余票数8张剩余票数7张剩余票数6张剩余票数5张剩余票数4张剩余票数3张剩余票数2张剩余票数1张剩余票数0张

同步方法:同步的对象是当前对象(this)

package com.chocus.demo1;public class ThreadDemo6 {  public static void main(String[] args) {    MyRunnable6 mr = new MyRunnable6();    Thread t = new Thread(mr);    Thread t2 = new Thread(mr);    t.start();    t2.start();  }}class MyRunnable6 implements Runnable {  private int ticket = 10;  @Override  public void run() {    for (int i = 0; i < 20; i++) {      method();    }  }  private synchronized void method() {    if (ticket > 0) {      ticket--;      try {        Thread.sleep(300);      } catch (InterruptedException e) {        // TODO Auto-generated catch block        e.printStackTrace();      }      System.out.println("剩余票数" + ticket + "张");    }  }}

结果

剩余票数9张剩余票数8张剩余票数7张剩余票数6张剩余票数5张剩余票数4张剩余票数3张剩余票数2张剩余票数1张剩余票数0张

Lock锁:比同步代码块和同步方法更灵活。同步代码块需要执行完毕后释放锁,而同步方法要方法执行完毕后释放锁。

package com.chocus.demo1;import java.util.concurrent.locks.ReentrantLock;public class ThreadDemo6 {  public static void main(String[] args) {    MyRunnable6 mr = new MyRunnable6();    Thread t = new Thread(mr);    Thread t2 = new Thread(mr);    t.start();    t2.start();  }}class MyRunnable6 implements Runnable {  private int ticket = 10;  ReentrantLock lock = new ReentrantLock();  @Override  public void run() {    for (int i = 0; i < 20; i++) {      method();    }  }  private void method() {    lock.lock();    try {      if (ticket > 0) {        ticket--;        try {          Thread.sleep(300);        } catch (InterruptedException e) {          // TODO Auto-generated catch block          e.printStackTrace();        }        System.out.println("剩余票数" + ticket + "张");      }    } finally {      lock.unlock();    }  }}

结果

剩余票数9张剩余票数8张剩余票数7张剩余票数6张剩余票数5张剩余票数4张剩余票数3张剩余票数2张剩余票数1张剩余票数0张