相关说明:
- 类锁控制类的所有实例的访问
- 对象锁锁住的是当前实例,对同一类的不同实例就没有限制
实验环节:
对象锁
class Object_Lock{
//代码块上 -- 锁住调用该方法的对象
public void funA(){
synchronized (Object_Lock.this){
for(int i = 1 ;i <=5;i++){
System.out.println(Thread.currentThread().getName()+"这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>"+i);
}
}
}
Object object =new Object();
//代码块上 -- 锁住任何一个对象
public void funB(){
synchronized (object){
for(int i = 1 ;i <=5;i++){
System.out.println(Thread.currentThread().getName()+"这是一个用在代码块上的对象锁(锁住任何一个对象)>>>"+i);
}
}
}
//方法上
public synchronized void funC(){
for(int i = 1 ;i <=5;i++){
System.out.println(Thread.currentThread().getName()+"这是一个用在方法上的对象锁>>>"+i);
}
}
}
实验1:测试`代码块上锁住调用该方法的对象
a)一个类的不同实例、
public void test1(){
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
Object_Lock o1 = new Object_Lock();
o1.funA();
}
},"Thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
Object_Lock o2 = new Object_Lock();
o2.funA();
}
},"Thread2");
thread1.start();
thread2.start();
}
实现结果:没有互斥地访问
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>1
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>1
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>2
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>2
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>3
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>3
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>4
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>5
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>4
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>5
b)同一个类的同一实例
public void test2(){
Object_Lock o = new Object_Lock();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
o.funA();
}
},"Thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
o.funA();
}
},"Thread2");
thread1.start();
thread2.start();
}
实验结果:互斥地访问
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>1
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>2
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>3
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>4
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>5
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>1
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>2
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>3
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>4
Thread2这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>5
实验2:测试锁住调用方法的对象和锁住其他对象
public void test3(){
Object_Lock o = new Object_Lock();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
o.funA();
}
},"Thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
o.funB();
}
},"Thread2");
thread1.start();
thread2.start();
}
实验结果:锁住的对象不同,不互斥
Thread2这是一个用在代码块上的对象锁(锁住任何一个对象)>>>1
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>1
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>2
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>3
Thread2这是一个用在代码块上的对象锁(锁住任何一个对象)>>>2
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>4
Thread2这是一个用在代码块上的对象锁(锁住任何一个对象)>>>3
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>5
Thread2这是一个用在代码块上的对象锁(锁住任何一个对象)>>>4
Thread2这是一个用在代码块上的对象锁(锁住任何一个对象)>>>5
实验3:测试方法和代码块
public void test4(){
Object_Lock o = new Object_Lock();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
o.funA();
}
},"Thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
o.funC();
}
},"Thread2");
thread1.start();
thread2.start();
}
实验结果:锁住的是同一对象,互斥
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>1
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>2
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>3
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>4
Thread1这是一个用在代码块上的对象锁(锁住调用该方法的对象)>>>5
Thread2这是一个用在方法上的对象锁>>>1
Thread2这是一个用在方法上的对象锁>>>2
Thread2这是一个用在方法上的对象锁>>>3
Thread2这是一个用在方法上的对象锁>>>4
Thread2这是一个用在方法上的对象锁>>>5
类锁:
控制类的所有实例的访问。
//类锁 : 控制类的所有实例的访问,当一个线程获取类锁时,其他线程必须等待
class Class_Lock{
//代码块上
public void funA(){
synchronized (Class_Lock.class){
for(int i = 1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+"这是一个用在代码块上的类锁>>>"+i);
}
}
}
//static synchronized
//代码块上
public static synchronized void funB(){
for(int i = 1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+"这是一个用在方法上的类锁>>>"+i);
}
}
}
实验1:不同类的实例访问代码块锁
public void test5(){
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
Class_Lock c1 = new Class_Lock();
c1.funA();
}
},"Thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
Class_Lock c2 = new Class_Lock();
c2.funA();
}
},"Thread2");
thread1.start();
thread2.start();
}
实验结果:互斥
Thread1这是一个用在代码块上的类锁>>>1
Thread1这是一个用在代码块上的类锁>>>2
Thread1这是一个用在代码块上的类锁>>>3
Thread1这是一个用在代码块上的类锁>>>4
Thread1这是一个用在代码块上的类锁>>>5
Thread2这是一个用在代码块上的类锁>>>1
Thread2这是一个用在代码块上的类锁>>>2
Thread2这是一个用在代码块上的类锁>>>3
Thread2这是一个用在代码块上的类锁>>>4
Thread2这是一个用在代码块上的类锁>>>5
实验2:不同类的实例访问代码块锁和static方法锁
public void test6(){
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
Class_Lock c1 = new Class_Lock();
c1.funA();
}
},"Thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
Class_Lock c2 = new Class_Lock();
c2.funB();
}
},"Thread2");
thread1.start();
thread2.start();
}
实验结果:互斥
Thread1这是一个用在代码块上的类锁>>>1
Thread1这是一个用在代码块上的类锁>>>2
Thread1这是一个用在代码块上的类锁>>>3
Thread1这是一个用在代码块上的类锁>>>4
Thread1这是一个用在代码块上的类锁>>>5
Thread2这是一个用在方法上的类锁>>>1
Thread2这是一个用在方法上的类锁>>>2
Thread2这是一个用在方法上的类锁>>>3
Thread2这是一个用在方法上的类锁>>>4
Thread2这是一个用在方法上的类锁>>>5