Java 同步锁

主要理清锁的使用和本质锁的是什么:
	synchronized:
synchronized是java中的一个关键字,在JVM层面上实现的,使用时不需要管理锁的获取和释放。(synchronized发生异常时,会自动释放线程占有的锁)
直接上代码:
public class SynchronziedTest implements Runnable{
    //非静态属性
    private int num;
    //非静态属性,加了volatile关键字(1.该值直接刷新到主存,2.禁止jvm指令重排)
    private volatile int count;
    ////静态属性
    private static int other;
    //静态属性
    private static int changme = 0;
    //静态属性,同时加上volatile关键字
    private static volatile int sum;
    //类的静态属性
    private static final Object obj = new Object();
    //据说,此锁更可提高性能。源于:锁的对象越小越好
    private static byte block[] = {};
    //方法上加同步,用的对象锁:锁住的是当前对象,不同对象操作时,线程不安全
    public synchronized void addNum(){
        num++;
    }
    //非静态方法中的代码块加同步
    public void addCount(){
        //锁住的是当前对象的类对象
        synchronized (this.getClass()){
            count+=2;
        }
    }
    //非静态方法中的代码块加同步,锁的是类的静态成员属性
    public void mulCount(){
        synchronized (SynchronziedTest.obj){
            count-=1;
        }
    }
    //非静态方法中的代码块加同步
    public void addOther(){
        //锁住的是当前对象的类对象
        synchronized (this.getClass()){
            other+=2;
        }
    }
    //非静态方法中的代码块加同步,锁的是类的静态成员属性(属性必须被static以及final修饰,否则报错)
    public void mulOther(){
        synchronized (SynchronziedTest.obj){
            other-=1;
        }
    }
    //静态方法加同步,对静态变量进行操作,锁的是当前类对象
    public synchronized static void addchangme(){
        changme+=5;
    }
    //静态方法中静态代码块加同步,对静态变量chanme进行操作
    public static void mulchangme(){
        //同步锁锁住的是该类的静态成员属性
        synchronized (SynchronziedTest.block){
            for (int i=0;i<2;i++){
                changme-=1;
            }
        }
    }
    //非静态方法加同步,操作静态属性
    public synchronized void sum(){
        sum+=10;
    }

    //非静态方法
    public void mulSum(){
        //代码块上加同步,操作静态属性
        synchronized (SynchronziedTest.class){
            for (int i=0;i<3;i++){
                sum-=1;
            }
        }
    }
    public void printer(){
        //计划值为2:实际值为1:,即同步没有生效
        System.out.println(Thread.currentThread().getName()+" num值为: " + num);
        //计划值为:实际值为1:,即同步没有生效
        System.out.println(Thread.currentThread().getName()+" count值为: " + count);
        //计划值为2:实际值为2:,即同步生效
        System.out.println(Thread.currentThread().getName()+" other值为: " + other);
        //计划值为6:实际值为6:,即同步生效
        System.out.println(Thread.currentThread().getName()+" changme值为: " + changme);
        //计划值为14:实际值为14:,即同步生效
        System.out.println(Thread.currentThread().getName()+" sum值为: " + sum);
    }
    @Override
    public void run() {
        addNum();
        addCount();
        mulCount();
        addOther();
        mulOther();
        addchangme();
        mulchangme();
        sum();
        mulSum();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        printer();
    }
}

public class Test {
    public static void main(String[] args) {
        Thread t1 = new Thread(new SynchronziedTest(),"线程1");
        Thread t2 = new Thread(new SynchronziedTest(),"线程2");
        t1.start();
        t2.start();
    }
}

运行结果:

线程2 num值为: 1
线程2 count值为: 1
线程2 other值为: 2
线程2 changme值为: 6
线程2 sum值为: 14
线程1 num值为: 1
线程1 count值为: 1
线程1 other值为: 2
线程1 changme值为: 6
线程1 sum值为: 14
确保多线程操作的资源是同一资源两种方式:单列(确保同一对象)/static关键字(确保类的同一属性)
	Lock:
Lock是一个接口,通过代码实现,使用时候需要手动进行锁的释放,如果没有主动释放,很容易造成死锁(需要在finally块中释放锁)
直接上代码:
public class LockTest implements Runnable{
    //非静态属性
    private int num;
    //非静态属性
    private int A;
    //非静态属性
    private int B;
    //非静态属性,加了volatile关键字(1.该值直接刷新到主存,2.禁止jvm指令重排)
    private volatile int count;
    ////静态属性
    private static int other;
    //静态属性
    private static int changme = 0;
    //静态属性,同时加上volatile关键字
    private static volatile int sum;
    //非静态锁
    private Lock lock1 = new ReentrantLock();
    //静态锁
    private static Lock lock2 = new ReentrantLock();
    public void addNum(){
        Lock lock3 = new ReentrantLock();
        lock3.lock();
        try {
            for (int i = 0;i<5;i++){
                num++;
            }
        }finally {
            lock3.unlock();
        }
    }
    public void mulNum(){
        Lock lock3 = new ReentrantLock();
        lock3.lock();
        try {
            num--;
        }finally {
            lock3.unlock();
        }
    }
    public void addCount(){
        lock1.lock();
        try {
            count+=2;
        }finally {
            lock1.unlock();
        }
    }
    public void mulCount(){
        lock1.lock();
        try {
            count-=1;
        }finally {
            lock1.unlock();
        }
    }
    public void addOther(){
        lock2.lock();
        try{
            other+=2;
        }finally {
            lock2.unlock();
        }
    }
      public void mulOther(){
        lock2.lock();
        try{
            other-=1;
        }finally {
            lock2.unlock();
        }

    }
    public static void addchangme(){
        lock2.lock();
        try{
            changme+=5;
        }finally {
            lock2.unlock();
        }
    }
    public static void mulchangme(){

        lock2.lock();
        try{
            for (int i=0;i<2;i++){
                changme-=1;
            }
        }finally {
            lock2.unlock();
        }
    }
    public void sum(){
        lock2.lock();
        try{
            for (int i=0;i<2;i++){
                sum+=10;
            }
        }finally {
            lock2.unlock();
        }
    }
    public void mulSum(){
        lock2.lock();
        try{
            for (int i=0;i<3;i++){
                sum-=1;
            }
        }finally {
            lock2.unlock();
        }
    }
    public void addA(){
        lock2.lock();
        try {
            for (int i = 0;i<3;i++){
                A++;
            }
        }finally {
            lock2.unlock();
        }
    }
    public void mulA(){
        lock2.lock();
        try {
            A--;
        }finally {
            lock2.unlock();
        }
    }
    public void addB(){
        lock1.lock();
        try {
            for (int i = 0;i<3;i++){
                B++;
            }
        }finally {
            lock1.unlock();
        }
    }
    public void mulB(){
        lock1.lock();
        try {
            B--;
        }finally {
            lock1.unlock();
        }
    }
    //多线程操作成功同步条件:
    //1.使用的全局锁(Lock为类的静态成员属性);
    //2.对类的全局变量进行操作(类的静态成员属性);
    public void printer(){
        //计划值为8:实际值为4:,即同步没有生效
        System.out.println(Thread.currentThread().getName()+" num值为: " + num);

        //计划值为2:实际值为1:,即同步没有生效
        System.out.println(Thread.currentThread().getName()+" count值为: " + count);
        //计划值为2:实际值为2:,即同步生效
        System.out.println(Thread.currentThread().getName()+" other值为: " + other);
        //计划值为6:实际值为6:,即同步生效
        System.out.println(Thread.currentThread().getName()+" changme值为: " + changme);
        //计划值为34:实际值为34:,即同步生效
        System.out.println(Thread.currentThread().getName()+" sum值为: " + sum);
        //计划值为4:实际值为2:,即同步不生效
        System.out.println(Thread.currentThread().getName()+" A值为: " + A);
        //计划值为4:实际值为2:,即同步不生效
        System.out.println(Thread.currentThread().getName()+" B值为: " + B);
    }
    @Override
    public void run() {
        addNum();
        mulNum();
        addCount();
        mulCount();
        addOther();
        mulOther();
        addchangme();
        mulchangme();
        sum();
        mulSum();
        addA();
        mulA();
        addB();
        mulB();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        printer();
    }
}
public class Test {
    public static void main(String[] args) {
        Thread t1 = new Thread(new LockTest(),"线程1");

        Thread t2 = new Thread(new LockTest(),"线程2");
        t1.start();
        t2.start();
    }

}
线程1 num值为: 4
线程1 count值为: 1
线程1 other值为: 2
线程1 changme值为: 6
线程1 sum值为: 34
线程1 A值为: 2
线程1 B值为: 2
线程2 num值为: 4
线程2 count值为: 1
线程2 other值为: 2
线程2 changme值为: 6
线程2 sum值为: 34
线程2 A值为: 2
线程2 B值为: 2
确保多线程操作的资源是同一资源两种方式:单列/static关键字
	结论:
使用同步锁,一定要搞清楚,需要使用类锁,还是对象锁;如果是不同对象多线程操作同一资源情况,要使用类锁;如果是同一个对象多线程操作同一资源时,需要使用对象锁。具体情况采用相应的锁进行同步问题。

文章有误,欢迎指出!

    原文作者:java锁
    原文地址: https://blog.csdn.net/JY_He/article/details/79669987
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞