Java中的锁
Java中的加锁操作有两种:
1.synchronized锁(jvm层的解决方案,也叫监视器锁)
在操作系统的层面使用的是互斥锁(mutex lock)
在Java中放在了对象头中。
2.手动锁Lock
操作锁的流程
- 1.尝试获取锁
- 2.使用锁
- 3.释放锁
synchronized锁
- package ThreadDeom;
- /**
- * user:ypc;
- * date:2021-06-12;
- * time: 14:12;
- */
- class Counter2 {
- private static volatile int count = 0;
- public void increase() {
- for (int i = 0; i < 10000; i++) {
- count++;
- }
- }
- public void decrease() {
- for (int i = 0; i < 10000; i++) {
- count--;
- }
- }
- public int getCount() {
- return count;
- }
- }
- public class ThreadDemo19 {
- public static void main(String[] args) throws InterruptedException {
- //声明锁对象,任何的对象都可以作为锁
- Object lock = new Object();
- Counter2 counter2 = new Counter2();
- Thread thread1 = new Thread(new Runnable() {
- @Override
- public void run() {
- //使用锁
- synchronized (lock) {
- counter2.decrease();
- }
- }
- });
- Thread thread2 = new Thread(() -> {
- synchronized (lock) {
- counter2.increase();
- }
- });
- thread1.start();
- thread2.start();
- thread1.join();
- thread2.join();
- System.out.println(counter2.getCount());
- }
- }
结果是:
synchronized使用场景
1.使用synchronized来修饰代码块(可以给任意的对象进行加锁操作)
- public class ThreadDemo19 {
- public static void main(String[] args) throws InterruptedException {
- //声明锁对象,任何的对象都可以作为锁
- Object lock = new Object();
- Counter2 counter2 = new Counter2();
- Thread thread1 = new Thread(new Runnable() {
- @Override
- public void run() {
- //使用锁
- synchronized (lock) {
- counter2.decrease();
- }
- }
- });
- Thread thread2 = new Thread(() -> {
- synchronized (lock) {
- counter2.increase();
- }
- });
- thread1.start();
- thread2.start();
- thread1.join();
- thread2.join();
- System.out.println(counter2.getCount());
- }
- }
2.使用synchronized来修饰静态方法(对当前的类进行加锁的操作)
- package ThreadDeom;
- /**
- * user:ypc;
- * date:2021-06-12;
- * time: 14:02;
- */
- class Counter1 {
- private static volatile int count = 0;
- public void increase() {
- for (int i = 0; i < 10000; i++) {
- count++;
- }
- }
- public void decrease() {
- for (int i = 0; i < 10000; i++) {
- count--;
- }
- }
- public int getCount() {
- return count;
- }
- }
- public class ThreadDemo18 {
- public static void main(String[] args) throws InterruptedException {
- Counter1 counter1 = new Counter1();
- Thread thread1 = new Thread(new Runnable() {
- @Override
- public void run() {
- counter1.decrease();
- }
- });
- Thread thread2 = new Thread(() -> {
- counter1.increase();
- });
- thread1.start();
- thread2.start();
- thread1.join();
- thread2.join();
- System.out.println(counter1.getCount());
- }
- }
3.使用synchronized来修饰普通的方法(对当前类的实例来进行加锁)
- package ThreadDeom;
- /**
- * user:ypc;
- * date:2021-06-12;
- * time: 14:12;
- */
- public class ThreadDemo20 {
- private static int num = 0;
- private static final int maxSize = 100000;
- public static void main(String[] args) throws InterruptedException {
- ThreadDemo20 threadDemo20 = new ThreadDemo20();
- Thread thread1 = new Thread(new Runnable() {
- @Override
- public void run() {
- threadDemo20.increase();
- }
- });
- Thread thread2 = new Thread(new Runnable() {
- @Override
- public void run() {
- threadDemo20. decrease();
- }
- });
- thread1.start();
- thread2.start();
- thread1.join();
- thread2.join();
- System.out.println(num);
- }
- //给静态的方法进行加锁,被加的锁是当前的对象。
- // public synchronized static void increase(){
- //给普通的方法进行加锁的操作
- public synchronized void increase() {
- for (int i = 0; i < maxSize; i++) {
- num++;
- }
- }
- // public synchronized static void decrease(){
- public synchronized void decrease() {
- for (int i = 0; i < maxSize; i++) {
- num--;
- }
- }
- }
synchronized注意事项
1.加锁的时候一定要使用同一把锁对象
Lock类的使用
也叫手动锁
- package ThreadDeom;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- /**
- * user:ypc;
- * date:2021-06-12;
- * time: 18:32;
- */
- public class ThreadDemo22 {
- private static int number = 0;
- private static final int maxSize = 100000;
- public static void main(String[] args) {
- //创建lock锁对象,lock是接口,不能实列化
- Lock lock = new ReentrantLock();
- Thread thread1 = new Thread(() -> {
- for (int i = 0; i < maxSize; i++) {
- lock.lock();
- try {
- number++;
- } finally {
- lock.unlock();
- }
- }
- });
- Thread thread2 = new Thread(() -> {
- for (int i = 0; i < maxSize; i++) {
- lock.lock();
- try {
- number--;
- } finally {
- lock.unlock();
- }
- }
- });
- System.out.println(number);
- }
- }
Lock锁使用的注意事项
lock()操作一定要放在try外面
如果放在try的里面:
1.try中抛出了异常,还没有加锁就释放了finally中的锁的操作了
2.如果放在了try,没加锁就释放了锁,就会抛出异常,就会将业务代码中的异常吞噬掉