答:非静态同步方法,静态同步方法。
package SellTicket;
public class SynRunnable{
public synchronized static void fun1(){
System.out.println("静态同步方法");
}
public static void fun2(){
System.out.println("静态非同步方法");
}
public synchronized void fun3(){
System.out.println("非静态同步方法");
try {
Thread.sleep(10000); //释放cpu资源,不会释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void fun4(){
System.out.println("普通方法");
}
public static void main(String[] args) {
SynRunnable demo1 = new SynRunnable();
new Thread(new Runnable(){
@Override
public void run() {
demo1.fun3();//非静态同步方法
}
},"A").start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(new Runnable(){
@Override
public void run() {
demo1.fun1();//静态同步方法
}
},"B").start();
}
}
输出结果:
非静态同步方法
静态同步方法
若选择连续运行非静态同步方法,两个结果之间需要等待。
线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。
线程同步中,在同步方法中
添加一个
Synchronized
修饰符,在对象上加锁,能够保证在同一时刻最多只有一个线程执行该段代码,其他线程等待该方法执行完,直到锁被释放。
- 非静态同步方法:
锁加在this(对象) 上 (类的实例)
- 静态同步方法:
锁加在类.class(对象)上
两个锁是不同的,所以自然不存在竞争。
线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他同步方法。
为什么同步静态方法就是锁的是该方法所在类的字节码文件对象 类名.class ?
虚拟机在加载类的时候 就会创建所有静态成员 这个时候方法是没有对象的,那这个时候的synchronized 只能使用类所对应的锁,也就是类锁,而且我们也能发现静态方法中并不能使用this关键字
锁的作用域是从锁被获取到其被释放的时间。锁的作用域可能太大,也有可能引起死锁。
对象锁和类锁的区别?
所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。
而所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!
调用同一个对象中非静态同步方法的线程将彼此阻塞。如果是不同对象,则每个线程有自己的对象的锁,线程间彼此互不干预。
调用同一个类中的静态同步方法的线程将彼此阻塞,它们都是锁定在相同的Class对象上。
静态同步方法和非静态同步方法将永远不会彼此阻塞,因为静态方法锁定在Class对象上,非静态方法锁定在该类的对象上。