关于锁的必须掌握的知识

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
lock是JUC里重要的内容,下面是容易出错的问题。记录一下


一、lock问题

代码如下(示例):

i/**
 * 	锁的问题
 * @author 祥哥
 *
 */
public class TestLock {
    
    
	public static void main(String[] args) {
    
    
		Cat cat = new Cat();
		//A线程执行吃
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat.eat();
			}
		},"A").start();
		//B线程执行玩
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat.play();
			}
		},"B").start();	
	}
}
//简单猫的类
class Cat{
    
    
	public synchronized void eat() {
    
    
		System.out.println(Thread.currentThread().getName()+ "猫吃鱼");
	}
	public synchronized void play() {
    
    
		System.out.println(Thread.currentThread().getName()+"猫玩球");
	}
}

请问线程A和线程B那个线程执行?

在这里插入图片描述
可以看到结果永远是A线程先执行,在去执行B。这是因为他们锁的是同一个对象,所以一次只能一个线程访问。举个通俗的例子就是:这个对象是一个房间,每一个线程进去然后上锁,所以需要排队一次一个线程的访问。

代码如下(示例):

public class TestLock {
    
    
	public static void main(String[] args) {
    
    
		Cat cat1 = new Cat();
		Cat cat2 = new Cat();
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat1.eat();
			}
		},"A").start();
		
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat2.play();
			}
		},"B").start();	
	}
}
class Cat{
    
    
	
	public synchronized void eat() {
    
    
		try {
    
    
		//这里睡了1分钟
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+ "猫吃鱼");
	}
	public synchronized void play() {
    
    
		System.out.println(Thread.currentThread().getName()+"猫玩球");
	}
}

请问线程A和线程B那个线程执行?

在这里插入图片描述
因为是两个对象,所以有两个锁。而第一个睡了1分钟,所以第二个就先执行了

/**
 * 	锁的问题两个对象 变成静态方法
 * @author 祥哥
 *
 */
public class TestLock {
    
    
	public static void main(String[] args) {
    
    
		Cat cat1 = new Cat();
		Cat cat2 = new Cat();
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat1.eat();
			}
		},"A").start();
		
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat2.play();
			}
		},"B").start();	
	}
}
class Cat{
    
    
	//这里变成了静态方法
	public static synchronized void eat() {
    
    
		try {
    
    
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+ "猫吃鱼");
	}
	public static synchronized void play() {
    
    
		System.out.println(Thread.currentThread().getName()+"猫玩球");
	}
	
}

请问线程A和线程B那个线程执行?

在这里插入图片描述
因为是静态方法,是虽然是创建了两次,static内存是共享的都在类库里。

/**
 * 	锁的问题两个对象 变成1个静态方法,1个普通方法
 * @author 祥哥
 *
 */
public class TestLock {
    
    
	public static void main(String[] args) {
    
    
		Cat cat1 = new Cat();
		Cat cat2 = new Cat();
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat1.eat();
			}
		},"A").start();
		
		new Thread(new Runnable() {
    
    
			@Override
			public void run() {
    
    
				cat2.play();
			}
		},"B").start();	
	}
}
class Cat{
    
    
	
	public static synchronized void eat() {
    
    
		try {
    
    
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+ "猫吃鱼");
	}
	public  synchronized void play() {
    
    
		System.out.println(Thread.currentThread().getName()+"猫玩球");
	}
	
}

请问线程A和线程B那个线程执行?

在这里插入图片描述
两个锁锁的不一样,一个是锁了静态的共享内存,一个是锁了对象。所以算是两个锁。

总结

总之主要就是static是公用一个内存的,所以锁起来就是同一个对象。

猜你喜欢

转载自blog.csdn.net/bluelimon/article/details/110354522