了解一下,一个线程中是否可以调用多个synchronized方法(包含方法,静态方法,代码块)
```java
public class SyncTest {
//获取CPU个数
private static int cpuCount = Runtime.getRuntime().availableProcessors();
private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(cpuCount, cpuCount * 2, 20,
TimeUnit.SECONDS, new LinkedBlockingQueue<>(20000));
static {
System.out.println("我的cpu颗数: " + cpuCount);
}
//成员变量,可被多个线程 共享
private static long a = 0L;
private static long b = 0L;
private static long c = 0L;
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(10000);
SyncTest lockobj = new SyncTest();
for (int i = 0; i < 10000; i++) {
threadPool.execute(() -> {
lockobj.sync(countDownLatch);
sync2(countDownLatch);
lockobj.sync3(countDownLatch);
});
}
// 等待所有的线程执行完再打印
countDownLatch.await();
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
}
/**
* 修饰生源方法,其使用的锁对应时当前类所在的实例对象(或者说当前方法的调用对象),也就是this
*
* @param countDownLatch
*/
private synchronized void sync(CountDownLatch countDownLatch) {
try {
a++;
} finally {
countDownLatch.countDown();
}
}
/**
* 修饰静态方法,使用的锁对象是当前类
*
* @param countDownLatch
*/
private synchronized static void sync2(CountDownLatch countDownLatch) {
try {
b++;
} finally {
countDownLatch.countDown();
}
}
private void sync3(CountDownLatch countDownLatch) {
try {
synchronized (countDownLatch) {
c++;
}
} finally {
countDownLatch.countDown();
}
}
}
结果:
a=3339
b=3334
c=3332
比如上面这段代码,如果三个代码在同一个线程,甚至两个代码在同一个线程,得出的结果集都不正确。
你的结果不对,是因为你的线程还没结束,你就输出结果了,不要用countDownLatch.await();
用threadPool.getActiveCount()判断它是不是执行完了,只要不等于0,就是还没结束
这一段改一下
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(10000);
SyncTest lockobj = new SyncTest();
for (int i = 0; i < 10000; i++) {
threadPool.execute(() -> {
lockobj.sync(countDownLatch);
sync2(countDownLatch);
lockobj.sync3(countDownLatch);
});
}
while (threadPool.getActiveCount()!=0){
Thread.sleep(100);
}
threadPool.shutdown();
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
}
在Java中,一个线程可以在同一时间调用多个synchronized方法(包括实例方法、静态方法和代码块)。每个synchronized方法都会获取相应的锁,以确保同一时间只有一个线程可以执行该方法。不同的synchronized方法可能使用不同的锁对象,但它们之间的互斥性是保证的。
在你提供的示例代码中,三个方法都使用了synchronized关键字修饰,分别对应不同的锁对象。这意味着在同一时间内,只能有一个线程执行其中一个synchronized方法。如果多个线程同时调用这三个方法,它们之间的执行顺序是不确定的,但每个方法内部的操作是原子性的。
关于你提到的结果不正确的问题,可能是因为线程之间的并发执行导致的。由于线程调度的不确定性,每个线程在获取到锁之前都可能被其他线程抢占执行。这可能导致某些线程在获取锁之前已经执行完毕,从而导致计数不准确。
为了解决这个问题,你可以使用同步工具类如CountDownLatch来确保所有线程执行完毕后再打印结果。在你的代码中,你已经使用了CountDownLatch来等待所有线程执行完毕,但可能存在其他并发问题导致结果不准确。你可以尝试在sync、sync2和sync3方法内部加上一些打印语句来观察每个线程的执行情况,以便更好地排查问题所在。
另外,你在代码中使用了线程池来执行任务,这会进一步增加并发执行的可能性。确保线程池的大小适当,以免造成过多的线程竞争和调度开销。