1.线程安全问题以及什么时候产生,解决的办法?
线程安全问题;
多个线程同时访问共享数据时可能会出现问题
什么情况下会产生:
当多线程访问共享数据时,由于cpu的切换,导致一个线程只执行关键代码的一部分,还没执行完此时另外一个线程参与进来,导致共享数据发生异常
如何解决:
通过线程同步机制synchronized+lock锁来解决
2.什么是死锁?防止?
死锁:
是指两个或以上的线程在执行过程中,由于竞争资源而造成的一种阻塞现象
防止:
1.设置超时时间
2.使用JUC包提供的并发类lock锁,而不是自己设计锁
3.尽量降低锁的粒度
4.尽量使用同步代码块,而不是同步方法
5.给线程取有意义的名字
6.避免嵌套锁
7.分配资源之前先看能不能回收回来资源
8.专锁专用
3.Synchronized关键字
当一个线程第一次运行到synchronize代码,获取到了 myObject对象的monitor锁,然后计数器就会+1,然后同一个线程第二次运行到synchronize代码,会再次获取到 myObject对象的monitor锁,这个就是重入加锁,计算器在加1,变成2,这个时候其他线程运行到第一次synchronize代码,会发现 myObject对象的monitor锁的计数器是大于0的,意味着被别人给加锁了,线程就会进入block阻塞状态,等待获取锁。
如果第一个线程出了 synchronized 修饰范围的话,就会有一个 moninorexit 的指令,此时,在底层获取锁的线程就会对那个对象的 monitor 的计数器减1,如果有多次重入加锁,就会对应多次减1,直到最后,计数器是0 ,然后,后面 block 阻塞的线程,会再次尝试获取锁,但是只有一个线程可以获取锁。
4.synchronize可以用在哪些地方
1.同步代码块:锁对象为括号中的对象
2.同步方法:锁对象为当前对象this
3.静态方法:class文件字节码对象
5.synchronized和lock锁的区别
1.lock是JUC包下提供封装好的锁,是类的概念;而synchronize是JVM虚拟机层面的一个关键字
2.lock是显示的加锁和解锁,解锁要在finally代码块,否则会死锁;synchronize为隐式的加锁和解锁
3.lock锁提供了尝试获取锁和设置获取锁时间的机制,可返回取锁的状态,获取不到可以选择放弃取锁;synchronize无法判断返回取锁状态,取锁不成功只能阻塞,没有lock灵活
4.lock锁可以被打断;synchronize锁阻塞不可打断
5.lock可以实现可重入、可公平锁;synchronize可以实现可重入,非公平锁
6.lock可以很灵活的通过线程角色类型去创建Condition监视器对象,调用await()、signal()、signalAll()进行线程通讯调度;而synchronize使用object对象本身作为监视器对象去调用wait(),进行线程通讯
7.lock提供了更丰富的锁分类,入读锁、写锁,更加细粒度去关注线程安全问题。