Java 哪个更有效?为什么?
在下面两种同步策略中,哪一种是优化的(如处理和生成的字节码),以及应该使用其中一种的场景Java 哪个更有效?为什么?,java,multithreading,concurrency,Java,Multithreading,Concurrency,在下面两种同步策略中,哪一种是优化的(如处理和生成的字节码),以及应该使用其中一种的场景 public synchronized void addName(String name) { lastName = name; nameCount++; nameList.add(name); } 或 还有什么是处理并发的可取方法: 使用java.util.concurrent包 使用上述低级方法 使用Job或UIJobAPI(如果在eclipsepde环境中
public synchronized void addName(String name)
{
lastName = name;
nameCount++;
nameList.add(name);
}
或
还有什么是处理并发的可取方法:
java.util.concurrent
包Job
或UIJob
API(如果在eclipsepde环境中工作)谢谢说不上来,因为这两个代码片段并不相等 差异(添加调用的同步性不足)可能是显著的,但可能不是。从你给我们的东西来看,很难说。
- 您更新的两段代码在语义上是相同的。但是,使用第二部分中的同步块可以实现更多的控制,因为您可以在不同的对象上同步,或者实际上,不同步不需要同步的方法部分
- 在可能的情况下,使用
比使用同步原语更可取,因为它允许您在更高的抽象级别上工作,并使用由非常熟练的人员编写并经过密集测试的代码java.util.concurrent
- 如果您在EclipsePDE中工作,使用它的API很可能是首选,因为它与平台的其余部分相关联
我个人不需要使用同步。块锁定除此之外的另一个对象,但这是SOers指出的有关同步的一种用法。块。我知道这可能是一个例子,但如果您打算编写这样的代码,请三思 在我看来,您似乎在复制信息,除非您看到需要对代码进行性能更改,否则不应该这样做。(这几乎是你永远不应该做的)
- 如果您确实需要在多个线程中运行这些代码,我会使用Collections.synchronizedList将名称列表制作成一个同步列表李>
- 姓氏应该是一个getter,它可以选择列表中的最后一个元素
- nameCount应该是列表的大小
如果您像现在这样做,那么还必须同步对引用变量的所有位置的访问,这将使代码的可读性大大降低,并且更难维护。从任何效率角度来看,这完全不重要 拥有块的意义在于可以指定自己的锁。您可以选择封装在对象中的锁,而不是使用
this
,这样您就可以更好地控制谁可以获得锁(因为您可以使该锁从对象外部无法访问)
如果使用this
作为锁(无论是在方法上放置synchronized还是在块上使用synchronized),程序中的任何内容都可以获得对象上的锁,并且很难对程序正在执行的操作进行推理
限制对锁的访问可以让您在可判定性方面获得巨大的收益,拥有这种确定性比在某个地方删除字节码更有益。您可以删除所有锁:
class Names {
AtomicReference<Node> names = new AtomicReference<Node>();
public void addName(final String name) {
Node old = names.get();
while (!names.compareAndSet(old, new Node(old, name))) {
old = names.get();
}
}
public String getName() {
final Node node = names.get();
return (node == null) ? null : node.name;
}
static class Node {
final Node parent;
final String name;
Node(final Node parent, final String name) {
this.parent = parent;
this.name = name;
}
int count() {
int count = 0;
Node p = parent;
while (p != null) {
count++;
p = p.parent;
}
return count;
}
}
}
类名{
AtomicReference名称=新的AtomicReference();
public void addName(最终字符串名){
Node old=names.get();
而(!names.compareAndSet(旧的,新的节点(旧的,名称))){
old=names.get();
}
}
公共字符串getName(){
final Node=names.get();
返回(node==null)?null:node.name;
}
静态类节点{
最终节点父节点;
最后的字符串名;
节点(最终节点父节点、最终字符串名称){
this.parent=parent;
this.name=名称;
}
整数计数(){
整数计数=0;
节点p=父节点;
while(p!=null){
计数++;
p=p.parent;
}
返回计数;
}
}
}
这基本上是一个Treiber堆栈实现。您可以获得大小和当前名称,并且可以轻松地对内容实现迭代器(尽管与示例中的迭代器相反)。根据您的需要,也可以使用替代的写上副本容器。感谢您指出遗漏的部分。我已经更新了代码片段。那么,
语义相同
是否意味着为它们生成的字节码相同?如果我喜欢其中一个而不是另一个,那么会有性能开销吗?@Favonius:不会,这意味着它们在同步方面会有相同的效果。我不知道这对性能是否有影响。拥有更多的字节码与此无关,因为只有机器码基因
class Names {
AtomicReference<Node> names = new AtomicReference<Node>();
public void addName(final String name) {
Node old = names.get();
while (!names.compareAndSet(old, new Node(old, name))) {
old = names.get();
}
}
public String getName() {
final Node node = names.get();
return (node == null) ? null : node.name;
}
static class Node {
final Node parent;
final String name;
Node(final Node parent, final String name) {
this.parent = parent;
this.name = name;
}
int count() {
int count = 0;
Node p = parent;
while (p != null) {
count++;
p = p.parent;
}
return count;
}
}
}