标签: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必须等待第一把锁执行完毕,才能执行后面的
}
标签:tst object ace one row throw 不用 trace 代码块
原文地址:https://www.cnblogs.com/020626zy/p/14660419.html