多线程之间实现同步

为什么有线程安全问题

  当多个线程同时共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。

线程安全问题前提条件:

  必须是在多线环境下,多个线程共享一个资源,对资源进行写操作(非原子性操作)

什么是多线程之间同步

  当多个线程共享同一个资源,不会受到其他线程的干扰。

需求说明:2个窗口同时卖100张火车票问题

运行结果:

 

线程安全解决办法。

  使用多线程之间同步synchronized或使用锁(lock)。

为什么使用线程同步或使用锁能解决线程安全问题呢?

  将可能会发生数据冲突问题(线程不安全问题)只能让当前一个线程进行执行。代码执行完成后释放锁,然后才能让其他线程进行执行。这样的话就可以解决线程不安全问题。

原来:

     1、有一个线程拿到了锁,其他线程已经有cpu执行权,一直排队等待其他线程释放资源。

     2、锁在代码执行完成后或者抛出异常情况下释放。

     3、锁已经被释放的话,其他线程开始获取锁进入同步方法。

使用多线程之间同步synchronized或使用锁(lock)

 同步代码块:就是将可能会发生线程安全问题的代码,给包括起来。

  synchronized(同一个数据){//synchronized(对象)//这个对象可以为任意对象 

     可能会发生线程冲突问题

  } 就是同步代码块 

同步的前提: 1,必须要有两个或者两个以上的线程 2,必须是多个线程使用同一个锁 必须保证同步中只能有一个线程在运行

好处:解决了多线程的安全问题 弊端:多个线程需要判断锁,较为消耗资源、抢锁的资源。

同步函数:

  在方法上修饰synchronized 称为同步函数;同步函数使用this锁。

  证明方式: 一个线程使用同步代码块(this作为锁),另一个线程使用同步函数。如果两个线程抢票不能实现同步,那么会出现数据错误。

  注意:一个线程使用同步函数,一个线程使用同步代码块非this,不能够同步。

静态同步函数:

  方法上加上static关键字,使用synchronized 关键字修饰 或者使用类.class文件。 静态的同步函数使用的锁是 该函数所属字节码文件对象 获取字节码对象可以用getClass方法获取,也可以用当前类名.class表示。

  加锁是为了保证同步,同步是保证数据安全,原子性问题。分布式锁、高并发和jvm没有任何关系,使用synchronized,ThreadLocal都属于jvm中同步。

死锁: 产生的原因是:同步中且套同步,相互不释放资源。

 

synchronized锁,有2个字节码指令:monitorenter和monitorexit,当方法进入时执行monitorenter,加上锁;方法执行完毕后,锁执行了monitorexit释放锁。

 任何对象都可以做为锁,那么锁的信息有存在对象的什么地方?锁存放在对象的头中,

  对象头的信息包含:Mark Word、ClassMetadata Address、Array Length

posted @ 2018-11-14 00:58  逍遥游jJ2EE  阅读(372)  评论(0编辑  收藏  举报