1.多线程同步代码块
1.什么情况下需要同步
(1)当多线程并发,有多段代码同时执行时,希望某一段代码执行过程中CPU不切换到其他的线程上工作,此时需要同步
(2)如果两段代码是同步的,那么同一时间只能执行一段代码,在一段代码执行完成前,CPU不会去执行另一段代码
2.同步代码块
使用synchronized关键字加上一个锁对象来定义一段代码,多个同步代码块如果使用相同的锁对象,那么他们就是同步的
3.案例
package javastudy01;
public class printer {
//目标是实现输出我是胡博士 和 同步代码块 ,分开输出,但由于没有使用同步代码块,会产生一下运行结果,不符合要求
public void printer1(){
System.out.print("我");
System.out.print("是");
System.out.print("胡");
System.out.print("博");
System.out.print("士\n");
}
public void printer2(){
System.out.print("同");
System.out.print("步");
System.out.print("代");
System.out.print("码");
System.out.print("块\n");
}
public static void main(String[] args) {
Thread t1 = new Thread(){
public void run(){
for(int i=0 ;i<=30;i++){
new printer().printer1();
}
}
};
Thread t2 = new Thread(){
public void run(){
for(int i=0 ;i<=30;i++){
new printer().printer2();
}
}
};
t1.start();
t2.start();
}
}
运行结果
很明显,线程没有按照我们预期的方式去运行
再给出同步代码块:
package javastudy01;
public class printer {
//目标是实现输出我是胡博士 和 同步代码块 ,分开输出,但由于没有使用同步代码块,会产生一下运行结果,不符合要求
Demo d = new Demo();
public void printer1(){
synchronized(d){ //多对象可以任意,但不能填入 new Demo()匿名对象,因为匿名对象产生的不是同一个对象
System.out.print("我");
System.out.print("是");
System.out.print("胡");
System.out.print("博");
System.out.print("士\n");
}
}
// Demo a = new Demo(); //此处的锁对象相同,表示是同步的填入a不起作用
public void printer2(){
synchronized(d){
System.out.print("同");
System.out.print("步");
System.out.print("代");
System.out.print("码");
System.out.print("块\n");
}
}
public static void main(String[] args) {
printer p = new printer();
Thread t1 = new Thread(){
public void run(){
for(int i=0 ;i<=100;i++){
p.printer1(); //注意:这里不能使用new printer()代替P 如果使用与下面的t2中的p就不是同一个对象,也无法实现输出要求
}
}
};
Thread t2 = new Thread(){
public void run(){
for(int i=0 ;i<=100;i++){
p.printer2();
}
}
};
t1.start();
t2.start();
}
}
class Demo {
}
运行结果
2.同步方法
实现:
public synchronized void printer(){
}
同步方法只需要在方法前加上关键字即可实现
1.非静态方法的锁对象是this
2.静态方法的多对象是字节码对象(printer.class)
因为static 静态优先于对象存在,不能定义this.super,且在创建对象时静态方法才有值
静态方法随类加载而加载