码迷,mamicode.com
首页 > 其他好文 > 详细

关于synchronized

时间:2021-04-15 12:38:55      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:tst   object   ace   one   row   throw   不用   trace   代码块   

1:对synchronized的理解

1.1 :假设t1和t2并发,开始执行时肯定有先有后

1.2:假设t1先执行,看到synchronized这个时候自动找“后面的共享对象”的对象锁,找到后并占有锁,然后执行后面同步代码块,在程序执行过程一直都是占有这把锁,直到同步代码块结束,锁才释放。

1.3:假设t1以被占用,t2也遇到synchronized关键字也会去占用后面共享对象这把锁,结果t1已占用,只能等到t1执行之后占用这把锁,进入同步代码块执行程序。

例如:两个人上同一个厕所,这个厕所为共享对象,t1和t2为两个人!!!!

  1.4:锁池lockpool: 运行状态下遇到synchronized就来到了锁池中(类似于阻塞状态)之后进入就绪状态。

这里共享对象的对象锁线程进入锁池找共享对象的对象锁是,会释放之前抢夺的CPU时间片,有可能找到也有可能找不到,没找到仍然会在锁池中等待,如果找到进入就绪状态抢夺CPU时间片。

2:线程同步机制语法(){

     同步代码块;

}

synchronized后面小括号必须为线程共享的,才能达到多线程排队同步

      共享对象:账户对象

      账户对象是共享的,所以this就是账户对象

Objectobj=newObject();  //这个不行因为obj为局部变量,不是共享对象
//synchronized (this){   //最完美方式
//synchronized (OBJ) //为实例变量,可以因为ACCOUNT是共享的
?
//synchronized (obj) {
synchronized ("abc"){   //"abc"在字符串常量池中   //所有线程都同步
   doublebefore=this.getBalance();
   doubleafter=before-money;
   try {
       Thread.sleep(1000);
  } catch (InterruptedExceptione) {
       e.printStackTrace();
  }
   this.setBalance(after);
}

 

3:java中三大变量

   3.1 : 实例变量 : 在堆中

           静态变量 : 在方法区中

           局部变量 : 在栈中

   3.2:以上三大变量中:局部变量永远也不会出现线程安全问题因为局部变量不共享,一个线程一个栈,局部变量在栈中,永不共享。

   3.3:实例变量在堆中,堆只有一个,静态变量在方法区中,方法区只有一个,所以栈和方法区都不共享。

4:扩大同步代码块

 

publicclassAccountThreadextendsThread {
?
   //两个线程必须共享同一个用户对象
   privateAccountact;
?
   //通过构造方法传递过来账户对象
   publicAccountThread(Accountact) {
       this.act=act;
  }
?
   publicvoidrun() {
       doublemoney=5000;
       //取款
       //synchronized (this) 这里的this是AccountThread对象并不共享!!
       synchronized (act) {  //共享,扩大了同步范围,但效率降低
           act.withdraw(money);
           System.out.println("账户"+act.getActno() +"取款成功,余额"+act.getBalance());
      }
  }
}

5:synchronized出现在实例方法中?  可以

  5.1:缺点:

synchronized出现在实例方法中,一定锁的是this。所以不灵活。

另外一个缺点:synchronized出现实例方法中表示整个方法体都需排队同步,可能会扩大同步范围导致程序效率低。

  5.2:优点:

节省代码

如果锁的就是this,建议使用。

publicsynchronizedvoidwithdraw(doublemoney) {
doublebefore=this.getBalance();
           doubleafter=before-money;
           try {
               Thread.sleep(1000);
          } catch (InterruptedExceptione) {
               e.printStackTrace();
          }
           this.setBalance(after);
      }
?
  }

6:大总结

synchronized有三种写法?

  6.1:同步代码块  灵活

    synchronized(线程共享对象){

                  同步代码块;

}

  6.2:在实例方法中使用synchronized表示共享对象一定是this并且同步代码块是整个方法体。

  6.3:在静态方法中使用synchronized表示类锁,类锁永远只有一把就算创建100个对象,类锁也只有一把。

7:关于synchronized面试题

   7.1:一个synchronized后面doOther不需要等待,两个对象没什么联系!!!

classMyClass{
   publicsynchronizedstaticvoiddoSome(){//因为是静态方法类锁一个对象一把锁,需要一个一个等待
       System.out.println("进入学习模式!!"); //一个synchronized后面doOther不需要等待
       //sleep保证doSome的执行
       try {
           Thread.sleep(1000*10);
      } catch (InterruptedExceptione) {
           e.printStackTrace();
      }
       System.out.println("还是进入学习模式!!");
  }
   public  voiddoOther(){
       System.out.println("进入学习模式!!");
       System.out.println("还是进入学习模式!!");//两个synchronized必须等待第一把锁执行完毕,才能执行后面的
?
  }

    7.2:两个synchronized必须等待第一把锁执行完毕,才能执行后面的

class MyClass{
  public synchronized static void doSome(){//因为是静态方法类锁一个对象一把锁,需要一个一个等待
      System.out.println("进入学习模式!!"); //一个synchronized后面doOther不需要等待
      //sleep保证doSome的执行
      try {
          Thread.sleep(1000*10);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      System.out.println("还是进入学习模式!!");
  }
  public synchronized void doOther(){
      System.out.println("进入学习模式!!");
      System.out.println("还是进入学习模式!!");//两个synchronized必须等待第一把锁执行完毕,才能执行后面的
?
  }

    7.3:两个对象不用等待,两个对象,两把锁

publicclassExam01 {
   publicstaticvoidmain(String[] args) throwsInterruptedException {
       MyClassmc1=newMyClass();
       MyClassmc2=newMyClass();//两个对象不用等待,两个对象,两把锁
?
       Threadt1=newMyThread(mc1);
       Threadt2=newMyThread(mc2);

   7.4:因为是静态方法类锁一个对象一把锁,需要一个一个等待

lass MyClass{
    public synchronized static void doSome(){//因为是静态方法类锁一个对象一把锁,需要一个一个等待
        System.out.println("进入学习模式!!"); //一个synchronized后面doOther不需要等待
        //sleep保证doSome的执行
        try {
            Thread.sleep(1000*10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("还是进入学习模式!!");
    }
    public  synchronized void doOther(){
        System.out.println("进入学习模式!!");
        System.out.println("还是进入学习模式!!");//两个synchronized必须等待第一把锁执行完毕,才能执行后面的

    }

关于synchronized

标签:tst   object   ace   one   row   throw   不用   trace   代码块   

原文地址:https://www.cnblogs.com/020626zy/p/14660419.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!