21道并发编程面试题(4)

      运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

  死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

9.volatile关键字有什么用途,和Synchronize有什么区别

  volatile用途:

    volatile是一个轻量级的Synchronize,保证了共享变量的可见性,能够防止脏读,被volatile关键字修饰的变量,如果值发生了改变,其他线程立刻可见

  区别:

    (1)volatile只能作用于变量,使用范围较小。synchronized可以用在变量、方法、类、同步代码块等,使用范围比较广。
    (2)volatile只能保证可见性和有序性,不能保证原子性。而可见性、有序性、原子性synchronized都可以包证。
    (3)volatile不会造成线程阻塞。synchronized可能会造成线程阻塞。

  什么是脏读,为什么发生脏读

    脏读是指当一个事务正在访问数据,并且对数据进行了修改。而这种修改还没有提交到数据库中,这时,另外一个事务也访问了这个数据,然后使用了这个数据。

10.先行发生原则

  10.1 程序次序原则:

    在一个线程内,按照代码的顺序,书写在前面的代码优先于书写后面的代码;

  10.2 管程锁定规则:

    一个unlock操作先行发生于后面对同一个锁的lock操作,注意是同一个锁;

  10.3 volatile原则:

    对于一个volatile变量的写操作先行发生于后面对变量的读操作;

  10.4 线程启动原则:

    Thread对象的start()方法优先于此线程的每一个动作;

  10.5 线程终止原则:

    线程中所有的操作都优先发生于此线程的每一个动作;

  10.6 对象中断原则:

    对象的interrupt()方法的调用优先发生于被中断线程的代码监测中断事件的发生;先中断再检测;

  10.7 对象终结原则:

    一个对象的初始化(构造函数执行完毕)完成优先发生于它的finalize()方法的开始;

  10.8 传递性

    如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;

11.并发编程线程安全三要素

  11.1 原子性(Synchronized, Lock)

    即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。

    在Java中,基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行。

  11.2 有序性(Volatile,Synchronized, Lock)

    即程序执行的顺序按照代码的先后顺序执行。

    在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

  11.3 可见性(Volatile,Synchronized,Lock)

    指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

    当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取共享变量时,它会去内存中读取新值。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c628f105a4eead5224f1076e66487750.html