27.JAVA编程之线程同步

线程同步的案例:

对于火车票,不同售票点,卖的票是一样的,这就涉及到资源共享,保证一张票只能卖给一个人,多个售票点好比多个线程

线程同步的概念:

1.多线程共享数据时,会发生线程不安全的情况
2.多线程共享数据必须使用同步

线程进行同步,有以下三种方法:

1.synchronized(要同步的对象){
要同步的操作;
}
示例代码:

public class ThreadDemo2 {
    public static void main(String[] args) {
        MyRunnable3 mr3 = new MyRunnable3();
        Thread t1 = new Thread(mr3);
        Thread t2 = new Thread(mr3);

        t1.start();
        t2.start();
    }
}

class MyRunnable3 implements Runnable{
    private int ticket = 10;
    Object obj = new Object();
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            if(ticket>0){
                synchronized (obj){
                    ticket--;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("购票成功,剩余票数:"+ticket);
                }
            }
        }
    }
}

运行效果:为什么到-1才结束???因为没有把判断放进同步线程中!!!



2.同步方法
public synchronized void method(){
要同步的操作;
}

public class ThreadDemo2 {
   public static void main(String[] args) {
       MyRunnable3 mr3 = new MyRunnable3();
       Thread t1 = new Thread(mr3);
       Thread t2 = new Thread(mr3);

       t1.start();
       t2.start();
   }
}

class MyRunnable3 implements Runnable{
   private int ticket = 10;
   Object obj = new Object();
   @Override
   public void run() {
       for (int i = 0; i < 50; i++) {
               method();
       }
   }

   //同步方法:同步的对象是当前对象(this)
   private synchronized void method(){
       if(ticket>0){
           ticket--;
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           System.out.println("购票成功,剩余票数:"+ticket);
       }
   }
}

运行效果:

3.Lock(ReentrantLock)
此方法更加灵活
示例代码:

import java.util.concurrent.locks.ReentrantLock;

public class ThreadDemo2 {
    public static void main(String[] args) {
        MyRunnable3 mr3 = new MyRunnable3();
        Thread t1 = new Thread(mr3);
        Thread t2 = new Thread(mr3);

        t1.start();
        t2.start();
    }
}

class MyRunnable3 implements Runnable{
    private int ticket = 10;
    Object obj = new Object();
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
                method();
        }
    }

    //互斥锁
    ReentrantLock lock = new ReentrantLock();
    //同步方法:同步的对象是当前对象(this)
    private void method(){
        lock.lock(); //锁
        try {
            if (ticket > 0) {
                ticket--;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("购票成功,剩余票数:" + ticket);
            }
        }finally { //finally确保一定会释放锁,避免死锁
            lock.unlock(); //释放锁
        }
    }
}

运行效果:

同步准则

1.多线程共享数据会有安全问题,使用同步可以解决安全问题,但同时会牺牲性能,所以同步的代码块要尽量保持简短,把不随数据变化的相关代码移出同步代码块
2.不要阻塞
3.在持有锁的时候,不要对其他对象调用方法

你可能感兴趣的:(27.JAVA编程之线程同步)