zoukankan      html  css  js  c++  java
  • 重学JAVA基础(八):锁的基本知识

    1.线程状态

      

    如上图,当我们新建一个线程,并start后,其实不一定会马上执行,因为只有操作系统调度了我们的线程,才能真正进行执行,而操作系统也随时可以运行其他线程,这时线程又回到可运行状态。这个过程是操作系统控制的,不是我们能控制的。我们能控制的是将线程变为blocked,并从blocked变为runable状态。

    在以前实验的wait和notify中,我当时并没有注意到notify后会进行锁阶段,以为notify后直接进入runable状态,等待操作系统调度。  从上面的图中可以看到,我们notify后,实际现场进入了locked状态,一个线程时就直接进入runable状态了,但是在多线程的情况下,因为我们wait或者notify时都是在同步中做的,只有获得同步锁的线程才有机会进入runable,其他线程还得等待。

    因此在这里主要是学习一下锁的原理

    2.锁

      1).内置锁

        java的每个对象都可以用作一个同步锁,这个锁就是内置锁,或者监视锁,通过同步方法或者代码块获得内置锁,也就是运用synchronized关键字字

          2).显示锁

        jdk提供的高级锁,比如Lock、Condition等,主要用于内置锁不方便实现的功能

    3.锁的一些特性

      1).可重入

        java线程时基于每线程计算锁的,在同一个线程中,可以再次进入该同步方法,而不会造成死锁。进入一次计数器加1,退出后减1。

               

    /**
         * 同步方法
         * @author tomsnail
         * @date 2015年4月18日 下午12:15:30
         */
        public synchronized void test1(){
            test1();
        }

          2).公平/非公平

        在公平的情况下,所有需要获得锁的线程,都有相同几率获得锁,反之,某些线程可以优先获得锁。

          

        /**
         * Creates an instance of {@code ReentrantLock}.
         * This is equivalent to using {@code ReentrantLock(false)}.
         */
        public ReentrantLock() {
            sync = new NonfairSync();
        }
    
        /**
         * Creates an instance of {@code ReentrantLock} with the
         * given fairness policy.
         *
         * @param fair {@code true} if this lock should use a fair ordering policy
         */
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    ReentrantLock锁的构造方法,就提供了公平/非公平的机制,而synchronized没有明确的公平/非公平性保证,因为是操作系统就行调度的。公平锁和非公平锁的具体实现和原理,以后再好好学习一下。

    4.死锁

        java因为是线程级别的,我借用进程的死锁:是指多个线程循环等待其他线程占用的资源而无限期的僵持下去的局面。

        死锁产生的必要条件:

        a).互斥条件

        某个资源在一段时间内,只能由一个线程占用

        b).不可抢占条件

               在该资源没有被释放前,其他线程不能抢占

        c).占用且申请条件

               该线程已经占有一个资源,但是又申请新的资源,但要申请的资源被其他线程占用

        d).循环等待条件

               多个线程等待其他线程释放资源

        

    public class DeadLockThread {
        static final String a = "a";
        static final String b = "b";
        
        public static void main(String[] args) {
            Thread a = new Thread(new DeadLockThread1());
            Thread b = new Thread(new DeadLockThread2());
            a.start();
            b.start();
        }
    }
    
    class DeadLockThread1 implements Runnable{
    
        @Override
        public void run() {
            testb();
        }
        
        public void testa(){
            synchronized (DeadLockThread.a) {
                System.out.println(DeadLockThread.a);
            }
        }
        
        public void testb(){
            synchronized (DeadLockThread.b) {
                System.out.println(DeadLockThread.b);
                
                
                testa();
            }
        }
        
    }
    
    class DeadLockThread2 implements Runnable{
    
        @Override
        public void run() {
            testa();
        }
        
        public void testa(){
            synchronized (DeadLockThread.a) {
                
                System.out.println(DeadLockThread.a);
                testb();
            }
        }
        
        public void testb(){
            synchronized (DeadLockThread.b) {
                System.out.println(DeadLockThread.b);
            }
        }
        
    }

    当上面四个条件同时满足时,就会产生死锁。

    当产生死锁的时候,我们破坏掉上面的四个条件就可以了。

  • 相关阅读:
    Oracle exp/imp导出导入命令及数据库备份 (转载)
    多表初始化
    调用别的窗体
    修复k8s内存泄露问题
    如何高效的学习(转)
    Ansible11:变量详解【转】
    沟通的方式方法
    shell中的循环及条件判断
    Tomcat参数优化
    将DataReader转化为DataTables的一个简单实现
  • 原文地址:https://www.cnblogs.com/TomSnail/p/4474024.html
Copyright © 2011-2022 走看看