java多线程并发安全问题,java开发安全问题

  java多线程并发安全问题,java开发安全问题

  1.多线程并发操作的安全问题是什么?当多个线程并发操作一个数据时,线程操作的时间不可控,可能导致操作数据的过程不按照程序设计的执行顺序运行,导致操作后数据混乱,严重时甚至导致系统瘫痪。

  2.用synchronized修饰的方法当一个方法用synchronized修饰时,该方法就变成了“synchronized方法”。如果多个线程不能同时进入方法的内容运行,就必须按顺序一个一个运行,这样才能避免并发安全问题。

  案例:抢豆豆事件(这样豆豆剩余量不能为负)公开课SyncDemo {

  公共静态void main(String[] args) {

  Table table=新表();

  线程t1=新线程(){

  公共无效运行(){

  while(true){

  int n=table . get bean();

  Thread.yield()。

  system . out . println(thread . current thread()。getname(),豌豆还剩 n );

  }

  }

  };

  线程t2=新线程(){

  公共无效运行(){

  while(true){

  int n=table . get bean();

  Thread.yield()。

  system . out . println(thread . current thread()。getname(),豌豆还剩 n );

  }

  }

  };

  t1 . start();

  T2 . start();

  }

  }

  类别表{

  private int bean=10

  public synchronized int getBean(){

  if(bean==0){

  抛出new RuntimeException(没有豌豆);

  }

  /*

  * yield()会使线程从运行状态转换到就绪状态,但可能没有效果。

  *暂停当前正在执行的线程对象(放弃当前拥有的cpu资源)当其工作时,

  *并执行其他线程。

  */

  线程。收益率();//模拟切换线程

  返回bean-;

  }

  }运行结果:

  当剩余豆量为0时,程序抛出异常。如果锁没有锁,有一定几率程序会跳过豆豆为0的条件继续运行。

  3.同步模块1。有效缩小同步范围,可以在保证并发安全的前提下,尽可能提高效率。

  2.同步块

  同步(同步监视器){

  //需要同步运行的代码片段

  }3.同步块可以更加灵活准确地锁定需要同步的代码片段,可以有效缩小同步范围,提高并发效率。但是,应该注意的是,只有多个线程才能看到同步监视器对象是同一个对象。

  案例:模拟商场买衣服公开课Syncdemo2 {

  公共静态void main(String[] args) {

  Shop Shop=new Shop();

  线程t1=新线程(){

  公共无效运行(){

  shop . buy();

  }

  };

  线程t2=新线程(){

  公共无效运行(){

  shop . buy();

  }

  };

  t1 . start();

  T2 . start();

  }

  }

  班级商店{

  公共void buy(){

  尝试{

  string name=thread . current thread()。getName();

  System.out.println(名称选择衣服);

  线程.睡眠(2000年);

  同步(这){

  System.out.println(名称试穿衣服);

  线程.睡眠(2000年);

  }

  System.out.println(名为退房离开);

  } catch (InterruptedException e) {

  //TODO自动生成的catch块

  e . printstacktrace();

  }

  }

  }运行结果:

  线程-1选择衣服

  Thread-0选择衣服

  试衣

  线程1签出并离开

  试穿衣服

  线程0检验和偏离分析:

  两个线程不会同时试穿衣服,因为在试穿会话中设置了同步块,使得线程有序运行试穿会话。

  4.用Synchronized 1修改静态方法。如果用Synchronized修改静态方法,那么这些方法必须具有同步效果。

  2.静态方法的对象是当前类的对象。

  3.类的每个实例用来表示jvm加载一个类。当jvm加载一个类时,它将实例化一个类的实例来表示它。每个类在jvm中只有一个类的实例,所以静态方法锁定当前类对应的类的实例。

  公共类Syncdemo3 {

  公共静态void main(String[] args) {

  线程t1=新线程(){

  公共无效运行(){

  foo . do some();

  }

  };

  线程t2=新线程(){

  公共无效运行(){

  foo . do some();

  }

  };

  t1 . start();

  T2 . start();

  }

  }

  Foo类

  公共同步静态void dosome(){

  尝试{

  string name=thread . current thread()。getName();

  System.out.println(名称运行dosome方法);

  thread . sleep(3000);

  System.out.println(名称操作结束);

  } catch(异常e) {

  e . printstacktrace();

  }

  }

  }5.互斥锁使用同步锁定多段代码,而锁的对象相同时,这些代码片段之间就是互斥锁,多个线程不能同时执行这些方法。

  公共类同步演示4 {

  公共静态void main(String[] args){

  Eoo Eoo=new Eoo();

  线程t1=新线程(){

  公共无效运行(){

  eoo。测试01();

  }

  };

  线程t2=新线程(){

  公共无效运行(){

  eoo。测试02();

  }

  };

  t1。start();

  T2。start();

  }

  }

  equal opportunity office 机会均等办公室级

  公共同步void test01(){

  字符串名称=线程。当前线程().getName();

  System.out.println(name 正在运行一方法);

  尝试{

  线程。睡眠(3000);

  } catch (InterruptedException e) {

  e。printstacktrace();

  }

  System.out.println(name 1运行完毕);

  }

  公共同步void test02(){

  字符串名称=线程。当前线程().getName();

  System.out.println(name 正在运行2方法);

  尝试{

  线程。睡眠(3000);

  } catch (InterruptedException e) {

  e。printstacktrace();

  }

  System.out.println(name 2运行完毕);

  }

  }运行结果:

  线程-0正在运行一方法

  螺纹-01运行完毕

  线程一正在运行2方法

  螺纹-12运行完毕结果分析:

  因为两个线程锁的对象相同,因此,当一个线程运行它的方法时,另一个线程不会一起运行运行它的方法,直到,一个线程运行结束后,他才可以进入这个类,来运行他的方法。

  6.死锁现象线程都是保持着自己的锁,但是都是等待对方来释放锁,就出现互相"僵持"的情况,导致程序不会继续向后运行。

  公共类同步演示5 {

  公共静态void main(String[] args) {

  Poo p=new Poo();

  线程t1=新线程(){

  公共无效运行(){

  p。方法1();

  }

  };

  线程t2=新线程(){

  公共无效运行(){

  p。方法二();

  }

  };

  t1。start();

  T2。start();

  }

  }

  便便类

  对象A=新对象();

  Object B=new Object();

  公共空的方法1(){

  字符串名称=线程。当前线程().getName();

  同步(一){

  尝试{

  System.out.println(name A正在运行。);

  线程。睡眠(3000);

  System.out.println(name A运行完毕);

  方法二();

  } catch(异常e) {

  e。printstacktrace();

  }

  }

  }

  public void method2(){

  字符串名称=线程。当前线程().getName();

  同步(B) {

  尝试{

  System.out.println(name B正在运行。);

  线程。睡眠(3000);

  System.out.println(name B运行完毕);

  方法1();

  } catch(异常e) {

  e。printstacktrace();

  }

  }

  }

  }运行结果:

  螺纹-0A正在运行。

  螺纹1B正在运行。

  螺纹-0A运行完毕

  螺纹1B运行完毕结果分析:

  虽然有输出结果,但是,程序并没有运行结束,两个线程都等待着对方来释放锁,而僵持不下。

  等待()和睡眠()的区别1 .等等是目标类中的方法,睡觉是线中的方法

  2.最主要的是睡眠方法调用后,并没有释放锁,使得线程仍然可以同步控制,睡觉不会让出出系统资源,睡觉方法可以在任何地方使用,而等待必须在同步方法或者同步块中使用,否则会抛出异常(Java。郎。illegalmonitorstateexception),等待方法不仅让出cpu,还会释放已占有的同步资源;

  3.睡觉必须捕获异常,而等等,诺菲和nofifyAll不需要捕获异常。

  4.睡觉是让某个线程暂时运行一段时间,其控制范围是由当前线程决定的,主动权在自己手里,而等等是由某个确定的对象来调用,主动权在某个对象手里。

  公共类等待演示{

  公共静态void main(String[] args) {

  线程t1=新线程my 01();

  线程T2=新线程my 02();

  t1。start();

  T2。start();

  }

  }

  类ThreadMy01扩展了线程{

  public static StringBuilder str=new StringBuilder();

  公共无效运行(){

  字符串名称=线程。当前线程().getName();

  同步(字符串){

  for(int I=0;i i ){

  尝试{

  海峡。等待(300);//完全释放锁

  //线程。睡眠(300);//不释放锁

  海峡。追加( a );

  System.out.println(名称字符串);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  }

  }

  }

  }

  //唤醒等待状态

  类ThreadMy02扩展了Thread{

  公共无效运行(){

  synchronized (ThreadMy01.str) {

  for(int I=0;i i ){

  尝试{

  线程.睡眠(2000年);

  system . out . println( 888 );

  } catch(异常e) {

  e . printstacktrace();

  }

  }

  //唤醒wait()状态

  thread my 01 . str . notify();

  }

  }

  }运行结果:

  888

  888

  螺纹-0a

  螺纹-0aa

  螺纹-0aa

  螺纹-0aaaa

  thread-0 aaaaaa结果分析:

  运行上述代码时,sleep睡眠2秒,但不执行wait,这意味着sleep不会放弃系统资源。

  线程的生命周期:

  版权归作者所有:原创作品来自博主小二上九8,转载请联系作者取得转载授权,否则将追究法律责任。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: