首页 > 代码库 > java中的线程问题是(四)——线程同步问题
java中的线程问题是(四)——线程同步问题
多线程的并发,给我们编程带来很多好处,完成更多更有效率的程序。但是也给我们带来线程安全问题。
解决问题的关键就是要保证容易出问题的代码的原子性,所谓原子性就是指:当a线程在执行某段代码的时候,别的线程必须等到a线程执行完后,它才能执行这段代码。也就是排队一个一个解决。
java处理线程两步的方法非常简单,只需要在需要同步的代码段,用:synchronized(Object){你要同步的代码}即可。
对同步机制的解释:
java任意类型的对象都有一个标志位,该标志位具有0、1两种状态,其开始状态为1,当某个线程执行了synchronized(Object)语句后,object对象的标志位变为0的状态,直到执行完整个synchronized语句中的代码块后,该对象的标志位又回到1状态。
当一个线程执行到synchronized(Object)语句的时候,先检查Object对象的标志位,如果为0状态,表明已经有另外的线程正在执行synchronized包括的代码,那么这个线程将暂时阻塞,让出CPU资源,直到另外的线程执行完相关的同步代码,并将Object对象的标志位变为状态,这个线程的阻塞就被取消,线程能继续运行,该线程又将Object的标志位变为0状态,防止其它的线程再进入相关的同步代码块中。
如果有多个线程因等待同一个对象的标志位面而处于阻塞状态时,当该对象的标志位恢复到1状态时,只会有一个线程能够进入同步代码执行,其它的线程仍处于阻塞的状态。
特别说明:
1、上面所说的标志位用术语讲就是对象锁,文件锁。数据库会有行锁、表锁等
2、synchronized(object)//object(就是对象锁)可以是任意类型对象
3 synchronized也可以修饰方法,当其修饰方法是,对象锁默认为(this)。
售票系统的演示
1 /** 2 * 功能:使用线程的注意事项 3 * 线程并发同步锁synchronized(Object){}的使用 4 */ 5 public class Thread05 { 6 public static void main(String[] args) { 7 //定义一个售票窗口 8 TicketWindow tw1=new TicketWindow(); 9 10 //使用三个线程同时启动 11 Thread t1=new Thread(tw1); 12 Thread t2=new Thread(tw1); 13 Thread t3=new Thread(tw1); 14 15 t1.start(); 16 t2.start(); 17 t3.start(); 18 } 19 } 20 21 //售票窗口类 22 class TicketWindow implements Runnable { 23 //共有2000张票 24 private int nums=2000; 25 private Dog myDog=new Dog(); 26 27 public void run() { 28 while(true){ 29 //出票速度是1秒出一张 30 try { 31 Thread.sleep(1000); 32 } catch (Exception e) { 33 e.printStackTrace(); 34 } 35 36 //认为if else要保证其原子性 37 //先判断是否还有票 38 synchronized(myDog){//synchronized(this){}为同步代码块 39 if(nums>0){ 40 //显示售票信息 41 //Thread.currentThread().getName()得到当前线程的名字 42 System.out.println(Thread.currentThread().getName()+"正在售出第"+nums+"张票"); 43 nums--; 44 }else{ 45 //售票结束 46 break; 47 } 48 } 49 } 50 } 51 }
java中的线程问题是(四)——线程同步问题