美文网首页慕课网BAT面试课程笔记
BAT 第十章 java高级知识点 多线程

BAT 第十章 java高级知识点 多线程

作者: fc82bb084ee7 | 来源:发表于2018-01-29 15:08 被阅读21次
Thread/Runnable的区别.
  1. 继承Thread类
  2. 实现Runnable接口, 弥补java语言的单继承的局限性.
    大多数使用实现Runnable接口的方式.
synchronized 关键字.

它叫做对象锁, 锁住的是"类的某个实体对象".

public class MyThreadObject {
    synchronized public void methodA() {
        // do something A.
        return;
    }

    public void methodB() {
        synchronized (this) {
            // do something B.
            return;
        }
    }
}

上面两个方法是等同的.

methodA()和methodB()都是普通方法, 必须先创建MyThreadObject的对象, 用对象去调用才行.
测试代码:

public void main() {
MyThreadObject obj = new MyThreadObject();
//thread 1 调用
obj.methodA();
//thread 2 调用
obj.methodB();


}

因为是同一个对象obj, 所以methodA()和methodB()的执行是有先后顺序的. 必须执行完一个方法后才能再执行另一个方法.

volatile 关键字的作用.

首先volatile只能去修饰类的成员变量. 不能修饰在方法前, 否则编译器报编译错误.
这篇文章讲的很清楚. https://www.cnblogs.com/Android9527/p/5403788.html

一句话: volatile告诉jvm, 它所修饰的变量不准许线程把它拷贝到自己的线程内存,需要直接访问主内存中的变量.

因为JVM为了提高效率, 对于普通的类成员变量, 每个线程会把主内存中的类成员变量的值, 拷贝一份到自己的线程内存中去使用, 在某些时刻才进行两块内存间的同步操作.

但要注意的是, 一个变量声明为volatile, 并不能保证对这个变量的操作是原子性的. 所谓原子性就是指操作中途CPU不会被打断.
为保证原子性. Java 5中引入了java.concurrent.Atomic.* 包, 对里面的所有类的一切操作都是原子性的.
最典型的例子是:

public static AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();
悲观锁, 乐观锁, 可重入锁, 这3个概念要清楚.

悲观锁:一段执行逻辑加上悲观锁,不同线程同时执行时,只能有一个线程执行,其他的线程在入口处等待,直到锁被释放. 典型的是Synchronized对象锁就叫做悲观锁.

乐观锁:一段执行逻辑加上乐观锁,不同线程同时执行时,可以同时进入执行,在最后更新数据的时候要检查这些数据是否被其他线程修改了(版本和执行初是否相同),没有修改则进行更新,否则放弃本次操作. 没找到合适的java类作为乐观锁, 平时开发接触乐观锁的机会不多, 了解它的概念即可.

从解释上可以看出,悲观锁具有很强的独占性,也是最安全的.而乐观锁很开放,效率高,安全性比悲观锁低,因为在乐观锁检查数据版本一致性时也可能被其他线程修改数据.

可重入锁(ReentrantLock)的概念
也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有需要获取该锁的代码,在这种情况下不受影响。

public class Test implements Runnable{  
  
    public synchronized void get(){  
        System.out.println(Thread.currentThread().getId());  
        set();  
    }  
  
    public synchronized void set(){  
        System.out.println(Thread.currentThread().getId());  
    }  
  
    @Override  
    public void run() {  
        get();  
    }  
    public static void main(String[] args) {  
        Test ss=new Test();  
        new Thread(ss).start();
    }  
}  

输出:

Threadid: 8
Threadid: 8

是同一个线程id, 在get()中继续调用set()方法, 虽然set()前加了synchronized, 但因为它是可重入锁, 所以不受影响, 可以继续调用下去.

在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁.

refer to:
https://www.cnblogs.com/softidea/p/5309312.html
http://blog.csdn.net/hongchangfirst/article/details/26004335
http://blog.csdn.net/a314773862/article/details/54095819

--- DONE. ---

相关文章

网友评论

    本文标题:BAT 第十章 java高级知识点 多线程

    本文链接:https://www.haomeiwen.com/subject/lubxzxtx.html