java多线程点滴记录2

经过某项目A的代码监察,发现很多多线程开发中易忽视的问题,以记录之。

 

1.  可能存在并发访问的对象没有同步控制

此为最典型的缺乏同步控制,对某些框架中的类不熟悉其使用

比如Servlet类本身是非线程安全的

比如并发使用同一RandomFileAccess对象进行读写,尽管对不同的文件部分进行读写,但由于其内部实现使用JNI,因此仍然会出现意向不到的问题

 

2.  深拷贝不完全导致对某个对象的并发读写

存在多线程对Map进行操作,然而不仅仅对Map本身操作,还对其value操作。如果直接对Map本身进行Clone,则无法对value和key进行clone。进而在同步块外对key/value进行并发读写:

 

		Map<String, Integer> map2 = null;
		synchronized (map) {
			map2 = (Map<String, Integer>) map.clone();
		}

		// do something to Integer 

3.  wait/notify造成的时序问题

如果期望wait被notify唤醒,那么务必保证调用wait的线程迟于调用notify的线程,否则wait会无人唤醒

 

4.  死锁

警惕环的出现,比如A、B同时调用方法t,t中存在一个同步块,A等待C线程某个信号出现,而C等待B线程退出,此时三者出现环

 

5.  CAS-ABA

有时候过于依赖CAS方法,比如多个线程只期望其中一个执行方法A,待A成功返回后其他等待的线程继续工作:

if (wait.compareAndSet(false, true)) {
			// 做实质操作
		} else {
			// 只有一个线程会激发,竞争失败的则等待,
			synchronized (object) {
				try {
					object.wait();
				} catch (InterruptedException e) {

				}
			}
		}

 如果wait变量置为true后,该时序操作上下文中不存在将其重置false,则尚可,若存在其他线程将其重置为false,时,那么使用CAS做并发控制则会出现ABA问题,使得某个期望只执行一次的操作会被执行多次。

 

6.  轮训等待中CPU利用率过高

一个线程的run方法持续观察某个变量,之后会激发某个操作,在不使用信号量等并发包时,通常有以下两种写法

boolean exist = false;
		// 第一种
		while (!exist) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
			}
		}

		// 第二种
		while (!exist) {
			synchronized (object) {
				try {
					object.wait(500);
				} catch (InterruptedException e) {
				}
			}
		}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值