什么是同步
- 同步就是加锁,不让其它人访问
- synchronized指的就是同步的意思
什么情况下需要同步
当多线程并发, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步,否则会有线程安全问题。
同步代码块
- 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
- 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的
- 使用同步锁时,应该尽是让锁的范围小点,才能提高性能
同步代码块案例:
package demo; public class Task implements Runnable{ private int tickets = 100; public void run(){ while(true){ synchronized (this){ if(tickets <= 0){ System.out.println("不好意思,票卖完了"); break; }else{ System.out.println(Thread.currentThread()+"恭喜你买到票,票号"+tickets); tickets--; } } } } }
package demo; public class SynchronizedDemo { public static void main(String[] args) { Task task = new Task(); Thread t1 = new Thread(task); Thread t2 = new Thread(task); Thread t3 = new Thread(task); t1.start(); t2.start(); t3.start(); } }
同步方法
- 使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的
- 非静态同步方法的锁是:this
- 静态同步方法的锁是:字节码对象(xx.class)
案例:卖火车票
- 需求,有ABCD4个窗口同时买票,只有100张票可买
- 多线程会有安全问题熟记
//火车站卖票【问题】 /** * 湖南到广州火车票:今天13:00 ,100张 * 火车站有4个窗口在同时卖票,要保证一张票只能被卖一次 * * 搞4个线程表示4个窗口 * * 通过加锁可以解决被多次卖同一张票的问题 * * 使用同步代码块 */ //创建卖票的任务 TicketTask task = new TicketTask(); //A窗口 Thread t1 = new Thread(task); t1.setName("窗口A"); //B窗口 Thread t2 = new Thread(task); t2.setName("窗口B"); //C窗口 Thread t3 = new Thread(task); t3.setName("窗口C"); //D窗口 Thread t4 = new Thread(task); t4.setName("窗口D"); //开启线程 t1.start(); t2.start(); t3.start(); t4.start(); class TicketTask implements Runnable{ //只有100张票 int ticket = 100; @Override public synchronized void run() { //卖票 while (true) { if (ticket <= 0) { System.out.println("不好意思,票已经卖完了..."); break; } else { System.out.println(Thread.currentThread() + "恭喜你卖到票,票号" + ticket); ticket--; } } } /*@Override public void run() { // TODO Auto-generated method stub *//** * 同步代码换括号里参数可以传任意对象 * this是一个锁对象 * 不同的一把锁,卖相同的票总是还是存在 *//* //卖票 while (true) { synchronized (String.class) {// 同步:加锁 if (ticket <= 0) { System.out.println("不好意思,票已经卖完了..."); break; } else { System.out.println(Thread.currentThread() + "恭喜你卖到票,票号" + ticket); ticket--; } } } }*/ /*@Override public void run() { // TODO Auto-generated method stub *//** * 同步代码换括号里参数可以传任意对象 *//* synchronized (this) { //卖票 while(true){ if(ticket <= 0){ System.out.println("不好意思,票已经卖完了..."); break; }else{ System.out.println(Thread.currentThread() + "恭喜你卖到票,票号" + ticket); ticket --; } } } }*/ }