Java锁的机制

锁的机制

以下代码以使用手机发邮件和发短信为例
线程的调度不是从上到下,而是和CPU相关。
两个线程在访问资源类的时候不是同时进入,锁是锁的当前对象,一旦A中锁住了方法sendEmail,则B只能等待A执行完方法后才能执行sendMessage
1、标准访问

// 资源类
class Phone{
	public synchronized void sendMessage() throw Exception{
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:一个对象里面如果有多个synchronized 方法,某一时刻内,只要一个线程去调用了一个synchronized方法,其它线程只能等待。
也就是说某一时刻内,只能有唯一一个线程去访问这些synchronized方法。

*****sendEmail
*********sendMessage

2、在邮件方法中暂停4S

// 资源类
class Phone{
	public synchronized void sendMessage() throw Exception{
		//暂停4秒,此方法来自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:

*****sendEmail
*********sendMessage

3、新增普通方法sayHello

// 资源类
class Phone{
	public synchronized void sendMessage() throw Exception{
		//暂停4秒,此方法来自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
	public void sayHello() throw Exception{
	System.out.println("*******sayHello");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//普通方法
		phone.sayHello();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:

*******sayHello
*****sendEmail

4、两部手机

// 资源类
class Phone{
	public synchronized void sendMessage() throw Exception{
		//暂停4秒,此方法来自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  Phone phone2=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//第二部手机发短信
		phone2.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:换了对象,不是同一个资源类,所以情况发生了变化,不同的锁

*********sendMessage
*****sendEmail

5、两个静态同步方法,同一部手机

// 资源类
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暂停4秒,此方法来自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public static synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//同一部手机调用静态同步方法
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:由于static是修饰类的,加锁后,是将整个class锁住,static修饰的锁属于全局锁,而非对象锁

*****sendEmail
*********sendMessage

6、两个静态同步方法,两部手机

// 资源类
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暂停4秒,此方法来自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public static synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  Phone phone2=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//第二部手机调用发短信的方法
		phone2.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:由于static是修饰类的,加锁后,是将整个class锁住,static修饰的锁属于全局锁,而非对象锁。对于静态同步方法,锁的是当前class

*****sendEmail
*********sendMessage

7、一个静态同步方法,一个普通同步方法

// 资源类
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暂停4秒,此方法来自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//调用普通同步方法
		phone.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:锁的对象是不一样的,一个 锁的是当前对象,另一个锁的是整个class。

*********sendMessage
*****sendEmail

8、一个静态同步方法,一个普通方法,两部手机

// 资源类
class Phone{
	public static synchronized void sendMessage() throw Exception{
		//暂停4秒,此方法来自Java.util.concurent包
		TimeUnit.Seconds.sleep(4);
		System.out.println("*********sendMessage");
	}
	public synchronized void sendEmail() throw Exception{
	 System.out.println("*****sendEmail");
	}
}
// 用于执行线程
public class LockDemo{
	public static void main(String[] args){
	  Phone phone=new Phone();
	  Phone phone2=new Phone();
	  new Thread(()->{
		try{
		phone.sendEmail();
		}catch(Exception e){
		e.printStackTrace();
}
	},"A").start;
	//睡眠1ms,人为让A线程先于B线程执行
	Thread.sleep(100);
	 new Thread(()->{
		try{
		//调用普通同步方法
		phone2.sendMessage();
		}catch(Exception e){
		e.printStackTrace();
}
	},"B").start;
	}
}

执行结果:全局锁和对象锁是两个不同的东西,实际上并无关系。一个是小米工厂,一个是小米手机

*********sendMessage
*****sendEmail
发布了13 篇原创文章 · 获赞 3 · 访问量 341

猜你喜欢

转载自blog.csdn.net/qq_40152865/article/details/102531585