(19)线程安全-同步锁

如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的

我们通过一个案例,演示线程的安全问题:

电影院要卖票,我们模拟电影院的卖票过程。假设要播放的电影是 “功夫熊猫3”,本次电影的座位共100个(本场电影只能卖100张票)。我们来模拟电影院的售票窗口,实现多个窗口同时卖 “功夫熊猫3”这场电影票(多个窗口一起卖这100张票)需要窗口,采用线程对象来模拟;需要票,Runnable接口子类来模拟

public class Ticketimplements Runnable {

int ticket =100;

@Override

public void run() {

while (true) {

if (ticket >0) {

//模拟选坐的操作

                    try {

Thread.sleep(1);

                    }catch (InterruptedException e) {

e.printStackTrace();

                    }

System.out.println(Thread.currentThread().getName() +"正在卖票:" +ticket--);

                }

           }

}

}public static void main(String[] args) {

//创建票对象

    Ticket ticket =new Ticket();

    //创建3个窗口

    Thread t1  =new Thread(ticket, "窗口1");

    Thread t2  =new Thread(ticket, "窗口2");

    Thread t3  =new Thread(ticket, "窗口3");

    t1.start();

    t2.start();

    t3.start();

}

结果显示:

正在买票:2

正在卖票:1

正在卖票:0

正在卖票:-1

电影院的票怎么能是-1呢,这就是线程不安全导致的,原因是 其他线程已经是0的时候有的线程还是直接再卖,显然不符合常理

1.2线程同步(线程安全处理Synchronized)

追其同步的根本的目的,是控制竞争资源的正确的访问,因此只要在访问竞争资源的时候保证同一时刻只能一个线程访问即可,因此java中提供了线程同步机制,能够解决上述的线程安全问题。

线程同步的方式有两种:

方式1:同步代码块

方式2:同步方法


1.2.1同步代码块

同步代码块: 在代码块声明上加上synchronized关键字

synchronized (锁对象) {

    可能会产生线程安全问题的代码

}

代码:

public class Ticketimplements Runnable {

int ticket =100;

Objectlock =new Object();

@Override

public void run() {

while (true) {

synchronized (lock) {

if (ticket >0) {

//模拟选坐的操作

                    try {

Thread.sleep(1);

                    }catch (InterruptedException e) {

                             e.printStackTrace();

                    }

                         System.out.println(Thread.currentThread().getName() +"正在卖票:" +ticket--);

                }

}

1.2.2同步方法

同步方法:在方法声明上加上synchronized

publicsynchronized void method(){

    可能会产生线程安全问题的代码

}

         同步方法中的锁对象是this

使用同步方法,对电影院卖票案例中Ticket类进行如下代码修改:

public

class Ticket implements Runnable {

    //共100票

    int ticket = 100;

    //定义锁对象

    Object lock = newObject();

    @Override

    public void run() {

        //模拟卖票

        while(true){

            //同步方法

            method();

        }

    }

//同步方法,锁对象this

    public  synchronized  void  method(){

        if (ticket > 0) {

            //模拟选坐的操作

            try {

                Thread.sleep(10);

            }catch (InterruptedException e) {

                e.printStackTrace();

            }

            System.out.println(Thread.currentThread().getName()+"正在卖票:" + ticket--);

        }

    }

}

静态同步方法: 在方法声明上加上static  synchronized

publicstatic synchronized void method(){

可能会产生线程安全问题的代码

}

你可能感兴趣的:((19)线程安全-同步锁)