java 多线程
以下代码高并发时会有啥问题,怎么优化
回答:
1、用了synchronized修饰了方法,又用synchronized修饰方法体,这两者是等效的,都是获得this(MyStack)的对象监视器并且临界区也是一致的,同是因为synchronized是可重入的,所以你这样用不会发生错误,但是这是不必要的;
2、可能会发生 @房管局规划部 中出现的错误,wait()可能出现假唤醒,而不满足临界条件,后续逻辑就会异常。
可以参看jdk wait()方法的注释描述:
所以,应该是这样:
synchronized( method_or_shared_object){ while(list.size()<=0)
wait();
// pop something...
}
一般来说,都需要在while(condition) wait()来防止假唤醒。
回答:
这段代码在高并发的情况下会出现锁竞争激烈,性能低下的问题。其它的死锁什么的不会出现,不要想太多了。高并发场景建议用concurrent linked queue,分段加锁,能降低锁竞争
回答:
实际运行了一下代码,会报错
notify:Thread-0Thread-99-pop:aaaa
--------------------
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(Unknown Source)
at java.util.ArrayList.remove(Unknown Source)
at MyStack.pop(MyStack.java:21)
at MyStack$1.run(MyStack.java:34)
调用代码如下
public static void main(String[] args) throws IOException { final MyStack test = new MyStack();
for (int i = 0; i < 100; i++) {
Thread t = new Thread() {
@Override
public void run() {
super.run();
try {
String str = test.pop();
System.err.println("pop:" + str);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
}
test.push("aaaa");
}
当第99个线程进入的时候,此时并没有进入wait,而直接取走了数据
此时notify启动了第一个线程Thread-0,然后就就越界了。。。
回答:
最好用线程池
回答:
synchronized
使用有问题,在方法头部定义使用了,就没必要在方法体内再次使用,属于可重入锁,无任何意义。
回答:
list变量每个线程进来都会new一个新的吧
回答:
首先synchronized
修饰方法的问题
对于非static方法,其作用相当于
synchronized(this)
:
synchronized void method(){// method body
}
// 等价于
void method() {synchronized(this){
// method body
}
}
对于static方法,其相当于
synchronized(YourClass.class)
:
class YourClass {synchronized static void method() {
// method body
}
// 等价于
static void method() {
synchronized(YourClass.class) {
// method body
}
}
}
其次关于假唤醒问题,就是@spance说的。官方docde描述是:
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup.
官方给出的解决方案是:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
以上是 java 多线程 的全部内容, 来源链接: utcz.com/p/170830.html