【Thread】- 类锁、对象锁

synchronized:同步锁关键字

Java中锁类型:对象锁、类锁

对象锁:顾名思义给对象上锁

当A线程访问一个object的时候,首先会获取该对象的对象锁,然后访问锁定的代码,而B线程访问同一个对象object锁定的代码区时,因为线程A之前已经获取到对象object的对象锁,因此线程B访问同步代码区的时候则会被阻塞,直到线程A执行完同步代码块,然后释放对象锁,B线程获取对象object的对象锁,才能进行访问同步代码块

用法:

synchronized (this){
//----同步代码块--------- 
}

this表示当前访问同步代码区的对象

特别注意:只要同步代码区的是同一个对象时才能实现互斥访问

类锁:顾名思义给类上锁-->具体就是给类的字节码上锁

当线程A访问类锁锁定的同步代码块时,线程B访问同步代码块,因为A之前已经获取类锁,因此线程B只能A执行完同步代码块后才能获取类锁进行访问

用法:

synchronized (Object.class){
//----同步代码块--------- 
}

注意:类锁是针对类的所有对象实例有效,换句话说所有的类实例访问类锁的同步代码块都会被同意管理,

扩展: 静态对象上加锁也属于类锁,因为静态对象属于类本身,而非对象实例

Java加锁方式:方法/对象实例/类

特别注意: 当一个类内部存在多个同步代码块时,如果锁定的是同一个对象,当A线程访问其中一个同步代码块时,任何其他的线程都不能访问其他的任何同步代码块,但是可访问非锁定的代码块

原因:对象的锁只有一把,只能给一个线程


需求:多个线程对同一个数进行加减操作

解决方法1:目标访问方法加锁:

package com.zhiwei.thread;

import java.util.Random;

public class ThreadCount01 {
	
   public static ThreadCount01Test threadCount01Test 
                    = new ThreadCount01Test();
   
   public static void main(String[] args){
	   
	   for(int i=0;i<5;i++){
		   new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){	
					if(new Random().nextInt()%2 ==0){
						threadCount01Test.add();
					}else{
						threadCount01Test.del();
					}
				}
				
			}
		}).start();
	   }
   }
}

class ThreadCount01Test{
	public int j=10;
	
	public  synchronized void add(){
		j++;
	System.out.println(Thread.currentThread().getName()+":j++:"+j);
	}
	public  synchronized void del(){
		j--;
	System.out.println(Thread.currentThread().getName()+":j--:"+j);
	}
}

结果:

分析: 方法上锁等于是给访问的对象上锁,而多个线程访问的使用的是同一个都对象ThreadCount01Test,达到互斥的效果。例如因此A线程访问其中的add方法时,因为对象锁定导致其他的线程不能访问add和del方法,只有等A线程访问完成同步代码块访问之后其他线程才可以访问,总之就是被锁定的方法每次只有一个对象的线程访问

解决方法2:类对象实例上锁:

package com.zhiwei.thread;
import java.util.Random;

public class ThreadCount02 {
	
   public static ThreadCount02Test threadCount02Test 
                        =new ThreadCount02Test();
   
   public static void main(String[] args){
	   
	   for(int i=0;i<10;i++){
		   new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){	
					if(new Random().nextInt()%2 ==0){
						threadCount02Test.add();
					}else{
						threadCount02Test.del();
					}
				}
				
			}
		}).start();
	   }
   }
}

class ThreadCount02Test{
	
	public int j=10;
	
	public  void add(){
		synchronized (this) {
			j++;
			System.out.println(Thread.currentThread().getName()+":j++:"+j);
		}
	}
	public  void del(){
		synchronized (this) {
			j--;
			System.out.println(Thread.currentThread().getName()+":j--:"+j);
		}
	}
}

结果:

分析: synchronized (this)锁定访问同步代码块的访问对象,因为多个线程都是使用同一个对象threadCount02Test访问,add/del只能有一个对象的一个线程访问,从而实现互斥的效果

解决方法3:类加锁

package com.zhiwei.thread;

import java.util.Random;

public class ThreadCount03 {
	
   public static ThreadCount03Test threadCount03Test01=new ThreadCount03Test();
   public static ThreadCount03Test threadCount03Test02=new ThreadCount03Test();
   
   public static void main(String[] args){
	   
	   for(int i=0;i<10;i++){
		   new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){	
					if(new Random().nextInt()%2 ==0){
						threadCount03Test01.add();
					}else{
						threadCount03Test01.del();
					}
				}
				
			}
		}).start();
	   }
	   
	   for(int i=0;i<10;i++){
		   new Thread(new Runnable() {
			
			@Override
			public void run() {
				while(true){	
					if(new Random().nextInt()%2 ==0){
						threadCount03Test02.add();
					}else{
						threadCount03Test02.del();
					}
				}
				
			}
		}).start();
	   }
   }
}

class ThreadCount03Test{
	
	public static int j=10;  //从属类本身:类的字节码加锁,影响所有的类势力
	
	public void add(){
		synchronized (ThreadCount03Test.class) {
			j++;
			System.out.println(Thread.currentThread().getName()+":j++:"+j);
		}
	}
	public  void del(){
		synchronized (ThreadCount03Test.class) {
			j--;
			System.out.println(Thread.currentThread().getName()+":j--:"+j);
		}
	}
}

结果:

分析: 使用类加锁的方式,即使多线程使用两个对象threadCount03Test01/threadCount03Test02访问都被类锁管理,从而实现多个对象互斥访问的效果,这里使用类锁的原因是将变量j设置为static属性,从属于类本身。

总结:

方法加锁和对象实例加锁只对同一个对象有效,类加锁适用于所有的类实例

转载于:https://my.oschina.net/yangzhiwei256/blog/3017255

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值