java如何解决线程安全问题
- 方式一:同步代码块
synchroized(同步监视器的对象){
需要被同步的代码
}
package threadtest; //使用同步代码块实现Runable接口的线程 public class Ruanble { public static void main(String[] args) { //创建实现类的对象 Num num=new Num(); //将此对象作为参数传递给Thread类的构造器,创建Thread类的对象 Thread thread1 =new Thread(num); Thread thread2 =new Thread(num); Thread thread3 =new Thread(num); //调用start()启动创建的Thread对象 thread1.setName("线程一"); thread2.setName("线程二"); thread3.setName("线程三"); thread1.start(); thread2.start(); thread3.start(); } } //创建一个类实现Runable接口 class Num implements Runnable{ int ticket=100; //定义同步监视器,多个线程共同使用唯一的同步监视器 Object obj=new Object(); //重写run方法 @Override public void run() { while (true) { synchronized (obj) { if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"开始售票,票号为"+ ticket); ticket--; }else { break; } } } } }
package threadtest; //同步代码块实现继承Thread的线程 public class ThreadTest { public static void main(String[] args) { //创建子类对象 EvenThread e1=new EvenThread(); EvenThread e2=new EvenThread(); EvenThread e3=new EvenThread(); //调用线程的start()启动 e1.setName("票口一"); e2.setName("票口二"); e3.setName("票口三"); e1.start(); e2.start(); e3.start(); } } //创建一个类继承与Thread类 class EvenThread extends Thread{ static int ticket=100; //定义同步监视器,多个线程共同使用唯一的同步监视器 static Object obj=new Object(); //重写run方法 @Override public void run() { while (true) { //synchronized (obj) {//方式一,确保同步监视器唯一 synchronized (EvenThread.class) {//EvenThread.class是唯一的 if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"开始售票,票号为"+ ticket); ticket--; }else { break; } } } } }
说明:共享数据------多个线程共同操作的数据
需要被同步的代码块,纪委操作共享的代码
同步监视器,俗称锁,任何一个类都可以充当同步监视器,但是,要求多个线程共用一个监视器
- 方式二:同步方法:如果操作共享数据的代码,完整的声明在相依的方法中,着我们可以考虑将此方法作为同步方法来写
- 非静态的同步方法的默认监视器是this,不能修改
- 静态的同步方法的监视器是当前类本身,不能修改
package threadtest; //创建同步方法实现Runable的线程 public class Ruanble { public static void main(String[] args) { //创建实现类的对象 Num num=new Num(); //将此对象作为参数传递给Thread类的构造器,创建Thread类的对象 Thread thread1 =new Thread(num); Thread thread2 =new Thread(num); Thread thread3 =new Thread(num); //调用start()启动创建的Thread对象 thread1.setName("线程一"); thread2.setName("线程二"); thread3.setName("线程三"); thread1.start(); thread2.start(); thread3.start(); } } //创建一个类实现Runable接口 class Num implements Runnable{ int ticket=100; //定义同步监视器,多个线程共同使用唯一的同步监视器 Object obj=new Object(); //重写run方法 @Override public void run() { while (true) { push(); } } //同步方法 public synchronized void push() {//这里有默认的同步监视器this,是唯一的 if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"开始售票,票号为"+ ticket); ticket--; } } }
//使用同步方法的来写继承Thread类的
package threadtest; public class ThreadTest { public static void main(String[] args) { //创建子类对象 EvenThread e1=new EvenThread(); EvenThread e2=new EvenThread(); EvenThread e3=new EvenThread(); //调用线程的start()启动 e1.setName("票口一"); e2.setName("票口二"); e3.setName("票口三"); e1.start(); e2.start(); e3.start(); } } //创建一个类继承与Thread类 class EvenThread extends Thread{ static int ticket=100; //定义同步监视器,多个线程共同使用唯一的同步监视器 static Object obj=new Object(); //重写run方法 @Override public void run() { while (true) { push(); } } //public synchronized void push() {//此时不加static,会在new EvenThred对象是,导致同步监视器不是唯一的,故加上static,让它先于类的创建而创建 public synchronized static void push(){ if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"开始售票,票号为"+ ticket); ticket--; } } }
方式三使用lock锁来确保安全,见下篇博客:链接---->
https://www.cnblogs.com/ylblikestudyJava/p/12378013.html