本篇文章转载自时间断崖
synchronized是java中解决并发问题的一种最简单最经常使用的方法,他能够确保线程互斥的访问同步代码html
同步代码块: 锁是括号里面的对象,对给定对象加锁,进入同步代码以前要得到给定对象的锁 同步普通方法: 锁是当前实例对象,进入同步代码以前要得到当前实例的锁 同步静态方法: 锁是当前类的class对象,进入同步代码以前要得到当前类对象的锁java
当不使用synchronized关键字的时候会发生什么并发
public class Ticket implements Runnable{ private int tickets = 10;//定义变量tickets,并赋值10 public void run() { while (true) { saleTicket(); if (tickets <= 0) { break; } } } public void saleTicket () { if (tickets > 0) { try { Thread.sleep(10); //通过的线程休眠 10秒 }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"---卖出的票"+tickets--); } } }
结果: 线程二---卖出的票10 线程一---卖出的票9 线程四---卖出的票8 线程三---卖出的票8 线程二---卖出的票7 线程一---卖出的票6 线程三---卖出的票5 线程四---卖出的票4 线程二---卖出的票2 线程一---卖出的票3 线程四---卖出的票1 线程三---卖出的票1 线程一---卖出的票0 线程二---卖出的票-1
能够看到卖出了0和-1张票,还卖了好几张1,在代码逻辑中当卖到0张的时候就中止卖票了。测试
public class Ticket implements Runnable{ private int tickets = 10;//定义变量tickets,并赋值10 Object lock = new Object();//定义任意一个对象,用做同步代码的锁 public void run() { while (true) { synchronized (lock) { //定义同步代码块 try { Thread.sleep(10); //通过的线程休眠 10秒 }catch (InterruptedException e) { e.printStackTrace(); } if (tickets > 0) { System.out.println(Thread.currentThread().getName()+"---卖出的票"+tickets--); }else {//若是tickets小于0,跳出循环 break; } } } } }
public class Ticket implements Runnable{ private int tickets = 10;//定义变量tickets,并赋值10 public void run() { while (true) { saleTicket(); if (tickets <= 0) { break; } } } public synchronized void saleTicket () { if (tickets > 0) { try { Thread.sleep(10); //通过的线程休眠 10秒 }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"---卖出的票"+tickets--); } } }
public class Ticket implements Runnable{ private static int tickets = 10;//定义变量tickets,并赋值10 public void run() { while (true) { saleTicket(); if (tickets <= 0) { break; } } } public static synchronized void saleTicket () { if (tickets > 0) { try { Thread.sleep(10); //通过的线程休眠 10秒 }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"---卖出的票"+tickets--); } } }
public class TestTicket{ public static void main(String[] args) { Ticket ticket = new Ticket();//建立ticket对象 //建立4个线程 new Thread(ticket,"线程一").start(); new Thread(ticket,"线程二").start(); new Thread(ticket,"线程三").start(); new Thread(ticket,"线程四").start(); } }
测试结果:线程
线程一---卖出的票10 线程一---卖出的票9 线程四---卖出的票8 线程四---卖出的票7 线程四---卖出的票6 线程四---卖出的票5 线程四---卖出的票4 线程四---卖出的票3 线程四---卖出的票2 线程四---卖出的票1
能够看到卖票结果没有超出预期code