java同步方法同步块_使用同步方法而不是同步块是否有优势?

有谁能举例说明同步方法优于同步块的优势吗?

#1楼

可以使用反射API检查同步方法。 这对于测试某些合同可能很有用,例如模型中的所有方法都已同步 。

以下代码段显示了Hashtable的所有同步方法:

for (Method m : Hashtable.class.getMethods()) {

if (Modifier.isSynchronized(m.getModifiers())) {

System.out.println(m);

}

}

#2楼

与线程同步。 1)永远不要在线程中使用synced(this),这是行不通的。 与(this)同步使用当前线程作为锁定线程对象。 由于每个线程都独立于其他线程,因此没有同步协调。 2)代码测试表明,在Mac上的Java 1.6中,方法同步不起作用。 3)Synchronized(lockObj),其中lockObj是在其上同步的所有线程的公共共享对象。 4)ReenterantLock.lock()和.unlock()工作。 参见Java教程。

以下代码显示了这些要点。 它还包含将替换ArrayList的线程安全Vector,以表明添加到Vector的许多线程不会丢失任何信息,而与ArrayList相同的线程可能会丢失信息。 0)当前代码显示由于竞争条件而导致的信息丢失A)注释当前标记为A的行,并取消注释其上方的A行,然后运行,方法会丢失数据,但不应丢失数据。 B)反向执行步骤A,取消注释B和//结束}。 然后运行以查看结果,没有数据丢失C)注释掉B,取消注释C。运行,请参见同步(此)丢失数据,这与预期的一样。 没有时间来完成所有的变体,希望对您有所帮助。 如果与此同步,或者方法同步可行,请说明您测试的Java和OS版本。 谢谢。

import java.util.*;

/** RaceCondition - Shows that when multiple threads compete for resources

thread one may grab the resource expecting to update a particular

area but is removed from the CPU before finishing. Thread one still

points to that resource. Then thread two grabs that resource and

completes the update. Then thread one gets to complete the update,

which over writes thread two's work.

DEMO: 1) Run as is - see missing counts from race condition, Run severa times, values change

2) Uncomment "synchronized(countLock){ }" - see counts work

Synchronized creates a lock on that block of code, no other threads can

execute code within a block that another thread has a lock.

3) Comment ArrayList, unComment Vector - See no loss in collection

Vectors work like ArrayList, but Vectors are "Thread Safe"

May use this code as long as attribution to the author remains intact.

/mf

*/

public class RaceCondition {

private ArrayList raceList = new ArrayList(); // simple add(#)

// private Vector raceList = new Vector(); // simple add(#)

private String countLock="lock"; // Object use for locking the raceCount

private int raceCount = 0; // simple add 1 to this counter

private int MAX = 10000; // Do this 10,000 times

private int NUM_THREADS = 100; // Create 100 threads

public static void main(String [] args) {

new RaceCondition();

}

public RaceCondition() {

ArrayList arT = new ArrayList();

// Create thread objects, add them to an array list

for( int i=0; i

Thread rt = new RaceThread( ); // i );

arT.add( rt );

}

// Start all object at once.

for( Thread rt : arT ){

rt.start();

}

// Wait for all threads to finish before we can print totals created by threads

for( int i=0; i

try { arT.get(i).join(); }

catch( InterruptedException ie ) { System.out.println("Interrupted thread "+i); }

}

// All threads finished, print the summary information.

// (Try to print this informaiton without the join loop above)

System.out.printf("\nRace condition, should have %,d. Really have %,d in array, and count of %,d.\n",

MAX*NUM_THREADS, raceList.size(), raceCount );

System.out.printf("Array lost %,d. Count lost %,d\n",

MAX*NUM_THREADS-raceList.size(), MAX*NUM_THREADS-raceCount );

} // end RaceCondition constructor

class RaceThread extends Thread {

public void run() {

for ( int i=0; i

try {

update( i );

} // These catches show when one thread steps on another's values

catch( ArrayIndexOutOfBoundsException ai ){ System.out.print("A"); }

catch( OutOfMemoryError oome ) { System.out.print("O"); }

}

}

// so we don't lose counts, need to synchronize on some object, not primitive

// Created "countLock" to show how this can work.

// Comment out the synchronized and ending {, see that we lose counts.

// public synchronized void update(int i){ // use A

public void update(int i){ // remove this when adding A

// synchronized(countLock){ // or B

// synchronized(this){ // or C

raceCount = raceCount + 1;

raceList.add( i ); // use Vector

// } // end block for B or C

} // end update

} // end RaceThread inner class

} // end RaceCondition outter class

#3楼

如前所述,当同步功能仅使用“ this”时,同步块可以将用户定义的变量用作锁定对象。 当然,您可以对应该同步的功能区域进行操作。 但是每个人都说,同步函数和使用“ this”作为锁定对象的块涵盖了整个函数之间没有区别。 这是不正确的,在两种情况下都会生成字节码。 在使用同步块的情况下,应分配局部变量,该变量保留对“ this”的引用。 结果,我们的功能会更大一些(如果您只有少数几个功能,则不相关)。

#4楼

关于使用同步块的重要说明:小心用作锁定对象!

上面来自user2277816的代码段说明了这一点,因为对字符串文字的引用用作锁定对象。 意识到字符串文字是在Java中自动插入的,您应该开始看到问题:在文字“锁”上同步的每一段代码都共享相同的锁! 这很容易导致完全不相关的代码死锁。

您不仅需要小心使用String对象。 装箱的基元也是一种危险,因为自动装箱和valueOf方法可以根据值重用相同的对象。

#5楼

通常在方法级别使用锁是很不礼貌的。 为什么通过锁定整个方法来锁定一段不访问任何共享资源的代码。 由于每个对象都有一个锁,因此可以创建虚拟对象来实现块级同步。 块级效率更高,因为它不会锁定整个方法。

这里有一些例子

方法级别

class MethodLevel {

//shared among threads

SharedResource x, y ;

public void synchronized method1() {

//multiple threads can't access

}

public void synchronized method2() {

//multiple threads can't access

}

public void method3() {

//not synchronized

//multiple threads can access

}

}

块级

class BlockLevel {

//shared among threads

SharedResource x, y ;

//dummy objects for locking

Object xLock = new Object();

Object yLock = new Object();

public void method1() {

synchronized(xLock){

//access x here. thread safe

}

//do something here but don't use SharedResource x, y

// because will not be thread-safe

synchronized(xLock) {

synchronized(yLock) {

//access x,y here. thread safe

}

}

//do something here but don't use SharedResource x, y

//because will not be thread-safe

}//end of method1

}

[编辑]

对于Vector和Hashtable这样的Collection ,当不使用ArrayList或HashMap时,它们将被同步,并且您需要设置sync关键字或调用Collections同步方法:

Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map

List myList = Collections.synchronizedList (myList); // single lock for the entire list

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值