我们都知道,java中可以使用synchronized对方法,或者变量加锁,那么,当我们使用synchronized对方法加锁,对变量加锁,shnchronized结合static一起使用,两个普通方法同时调用一个使用synchronized方法等等情况下,会出现什么样的效果呢?
结论:
这里先把结论写在开头,下面的都是实验过程,想直接看结论的可以不看下面的。
- 一个加锁方法和一个未加锁方法之间不会互相影响,因为第一个方法加了锁,锁住的只是方法域里面的这一个方法,对其它的方法并不会影响,如果我们在一个线程中调用上锁的方法,即使在这个线程里调用了sleep方法,也只是sleep了当前的线程,对另一个线程没有影响,即使是用的同一个对象。
- 如果两个方法都使用了synchronized加锁,这是对每个这个类的对象的两个方法加锁,当我们在两个线程中使用同一对象运行这两个加锁方法,会受到锁的影响,但是如果使用两个这个类的对象运行,就不会受到影响
- 如果两个方法都使用了synchronized static加锁,锁住的是这个类的静态方法,也就是说这个类的所有实例对象执行这两个方法的时候都会受到影响
- 通过两个加锁方法调用同一个普通方法和通过两个普通方法调用同一个加锁方法的效果一样,都是对过程加了锁
实验过程:
1.在两个线程中使用同一对象先调用加锁方法再调用未加锁方法
对象的类:
public class Lab {
public synchronized void fun1()
{
System.out.println("调用加锁方法");
try {
Thread.sleep(2000);//在方法中沉睡2秒,达到锁住的效果
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("加锁方法执行完毕");
}
public void fun2()
{
System.out.println("调用未加锁方法");
}
}
主方法:
public class Test {
public static void main(String[] args) {
Lab lab = new Lab();
new Thread(new Runnable() {
public void run() {
lab.fun1();//调用加锁方法
}
}).start();
new Thread(new Runnable() {
public void run() {
lab.fun2();//调用未加锁方法
}
}).start();
}
}
执行结果:
可以看到,在两个线程中使用同一对象先调用加锁方法再调用未加锁方法并不会造成第二个方法因为第一个方法锁住而无法执行,两个方法并发执行。
2.在两个线程中使用同一对象调用同一方法
public class Lab {
public synchronized void fun1()
{
System.out.println("调用加锁方法");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("加锁方法执行完毕");
}
public void fun2()
{
System.out.println("调用未加锁方法");
}
}
public class Test {
public static void main(String[] args) {
Lab lab1 = new Lab();
new Thread(new Runnable() {
public void run() {
lab1.fun1();//调用加锁方法
}
}).start();
new Thread(new Runnable() {
public void run() {
lab1.fun1();//调用未加锁方法
}
}).start();
}
}
执行结果:
在等待两秒钟上一个加锁方法执行完毕了之后才执行第二遍,证明加锁成功。
3.在两个线程中使用同一对象先调用静态加锁方法再调用未加锁方法
public class Lab {
public synchronized static void fun1()//改为静态加锁方法
{
System.out.println("调用加锁方法");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out