夜光带你走进 Java 成神之路(四十一)擅长的领域

夜光序言:

 

 

我都舍不得欺负的人,哪能让别人欺负?

 

正文:

                           以道御术 / 以术识道

package 深入理解volatile原理与使用;

//保证可见性的前提
//多个线程拿到的是同一把锁,否则是保证不了的
public class Demo {

    //volatile保证线程的一致性
    public volatile int a = 1; //变量上面加上一个volatile

    public synchronized int getA() {  //这里加上一把锁
        return a;
    }

    public synchronized void setA(int a) {  //这里加上一把锁
        try {
            Thread.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.a = a;
    }

    //一个线程在get,另外一个线程在set,很大情况下会出现线程安全问题
    public static void main(String[] args) {

        //我们先new一个对象出来
        Demo d = new Demo();

        d.a = 10;

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(d.a);
            }
        }).start();

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("最终的结果为:" + d.getA());

    }

}

package 深入理解volatile原理与使用;

public class Demo2 {

    //volatile关键词保证一下
    public volatile boolean run = false;

    public static void main(String[] args) {
        Demo2 demo2 = new Demo2();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=1;i<=10;i++){
                    System.err.println("执行了第" + i + "次");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                demo2.run = true;
            }
        }).start();

        //第二个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(!demo2.run){
                    //不执行
                }
                System.err.println("线程2执行了~~");
            }
        })
        .start();

    }

}

package Lock接口认识和使用;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//夜光
public class Sequence {

    private int value;
    Lock lock = new ReentrantLock(); //使用这个就可以了

    
    public int getNext(){  //相当于一个门,加一把锁

        lock.lock();
        int a = value++;
        lock.unlock(); //释放锁

        return value++;
    }


    public static void main(String[] args) {
        //我们调用的时候
//        new Sequence().getNext();

        //1. 下面这种方式面对多线程,会出现不可预期的问题
//        Sequence s = new Sequence();
//        while(true){ //多次调用
//            System.out.println(s.getNext());
//        }

        //2. 我们看看下面这种方式
        Sequence s = new Sequence();
        new Thread(new Runnable() {
            @Override
            public void run() {
                //下面,我们不停地去调用生成器
                while (true){
                    System.out.println(Thread.currentThread().getName()
                    +""+s.getNext());
                    try {
                        Thread.sleep(1000);  //休息一会儿
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        //然后,我们重写多个
        //嗯唔
        //第二个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                //下面,我们不停地去调用生成器
                while (true){
                    System.out.println(Thread.currentThread().getName()
                            +""+s.getNext());
                    try {
                        Thread.sleep(1000);  //休息一会儿
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();


        //第三个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                //下面,我们不停地去调用生成器
                while (true){
                    System.out.println(Thread.currentThread().getName()
                            +""+s.getNext());
                    try {
                        Thread.sleep(1000);  //休息一会儿
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();



    }

}

package 自旋锁死锁重入锁.可重入锁;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class MyLock implements Lock {

    //怎么判断第一个哈
    private boolean isLocked = false;


    @Override
    public synchronized void lock() {  //我们加上这个关键词,进来的线程要等待
        while (isLocked)  //只要为true,就~
            //.....
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        isLocked = true;
    }

    //第一个资源执行完毕,需要释放锁
    //那么我们则

    @Override
    public synchronized void unlock() {  //synchronized必须要加上这个
        isLocked = false;
        notify();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }


    @Override
    public Condition newCondition() {
        return null;
    }
}
package 自旋锁死锁重入锁.可重入锁;

//Sequence,我们写一个这个
public class Sequence {

    private MyLock lock = new MyLock(); //我们先构建一下~

    private int value;

    public int getNext(){
        lock.lock();
        value++;
        lock.unlock();

        return value;
    }

    public static void main(String[] args) {

        Sequence s = new Sequence();

        //现在,我们进行一下测试,夜光:三个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(s.getNext());
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(s.getNext());
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(s.getNext());
            }
        }).start();


    }

}

上面表示不可重入

那么下面,我们改成可重入的

可重入的锁,需要记住当下的线程

package 自旋锁死锁重入锁.可重入锁;

//我们说这个锁是可以重入的,我们来写一个例子
public class Demo {

    MyLock lock = new MyLock();

    public void a(){
        lock.lock();
        System.out.println("a");
        //这里,我们调用b方法
        b();
        lock.unlock();
    }

    public void b(){
        lock.lock();
        System.out.println("b");
        lock.unlock();
    }

    //然后,我们来测试
    public static void main(String[] args) {
        Demo d = new Demo();
        //然后,我们来创建线程
        //嗯唔

        //我们只要调用a就可以了,因为a里面包含了b
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.a();
            }
        }).start();

//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                d.b();
//            }
//        }).start();

    }

}
package 自旋锁死锁重入锁.可重入锁;

//Sequence,我们写一个这个
public class Sequence {

    private MyLock lock = new MyLock(); //我们先构建一下~

    private int value;

    public int getNext(){
        lock.lock();
        value++;
        lock.unlock();

        return value;
    }

    public static void main(String[] args) {

        Sequence s = new Sequence();

        //现在,我们进行一下测试,夜光:三个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true)
                System.out.println(s.getNext());
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true)  //我们加上一个这个
                System.out.println(s.getNext());
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true)
                System.out.println(s.getNext());
            }
        }).start();


    }

}
package 自旋锁死锁重入锁.可重入锁;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class MyLock implements Lock {

    //怎么判断第一个哈
    private boolean isLocked = false;

    //为了实现可重入锁
    //我们进行必要的改造
    //首先,需要记住当下的线程
    private Thread lockBy = null; //有点帅

    //锁的数量
    private int lockCount = 0;

    @Override
    public synchronized void lock() {  //我们加上这个关键词,进来的线程要等待

        Thread currentThread = Thread.currentThread();//嗯唔

        while (isLocked && currentThread != lockBy)  //只要为true,就~
            //.....
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        isLocked = true;
        lockBy = currentThread;
        lockCount++; //递增
    }

    //第一个资源执行完毕,需要释放锁
    //那么我们则

    @Override
    public synchronized void unlock() {  //synchronized必须要加上这个
        if (lockBy == Thread.currentThread()){  //如果是相等的
            lockCount--;

            if (lockCount == 0){
                notify();
                isLocked = false;
            }

        }
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }


    @Override
    public Condition newCondition() {
        return null;
    }
}
发布了1477 篇原创文章 · 获赞 281 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/weixin_41987706/article/details/103685451