Java中线程安全问题解决方案
线程安全问题:多个线程操作同一个属性时,会有安全问题
方式一:同步代码块
说明
① 将存在线程安全的代码,用synchronized同步代码块包裹(上锁、解锁)
② 如果有线程正在执行同步代码块中的代码,则其它线程需要等待此线程执行完之后,再继续抢占CPU执行权
③ synchronized(同步监视器)
,同步监视器必须是唯一的对象,相对于所有线程而言,他们都需要使用同一个对象(任何对象都可以,实现Runnable方式中最简单的是this,继承Thread方式中最简单的是当前类.class)
-
实现Runnable方式
public class Test { public static void main (String[] args) { Ticket t = new Ticket(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } } class Ticket implements Runnable { int ticket = 10; public void run() { while(true) { // 使用this充当唯一的对象 synchronized(this) { // 【ticket-start】 下面部分代码操作了公共属性ticket,为了防止线程安全问题,需要使用synchronized包裹 if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "-票号为:" + ticket--); } else { System.out.println("已售完"); break; } // 【ticket-end】 } } } }
-
继承Thread方式
public class Test { public static void main (String[] args) { } } class Ticket extends Thread { static int ticket = 10; public void run() { while(true) { // 使用Ticket.class充当唯一的对象 synchronized(Ticket.class) { // 【ticket-start】 下面部分代码操作了公共属性ticket,为了防止线程安全问题,需要使用synchronized包裹 if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "-票号为:" + ticket--); } else { System.out.println("已售完"); break; } // 【ticket-end】 } } } }