Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用synchronized是否使此代码具有顺序性?_Java_Multithreading_Threadpool_Executorservice_Synchronized - Fatal编程技术网

Java 使用synchronized是否使此代码具有顺序性?

Java 使用synchronized是否使此代码具有顺序性?,java,multithreading,threadpool,executorservice,synchronized,Java,Multithreading,Threadpool,Executorservice,Synchronized,我是线程池新手,正在学习使用同步 该代码存在竞争条件问题: import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit ; public class Counter implements Runnable{ int count; public Counter(){ count=0;

我是线程池新手,正在学习使用同步

该代码存在竞争条件问题:

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit ;
public class Counter implements Runnable{
    int count;
    public Counter(){
        count=0;
    }
    public void run(){
        count++;
    }
    public static void main(String[] args) throws 
    InterruptedException{
        ExecutorService exec=Executors.newFixedThreadPool(2);
        Counter task=new Counter();
        for (int i=0;i<1000;i++ ) {
            exec.execute(task); 
        }
        exec.shutdown();
        exec.awaitTermination(50L,TimeUnit.SECONDS);
        System.out.println(task.count);
    }
}
在该代码中,考虑了竞争条件:

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit ;
public class Counter implements Runnable{
    int count;
    public Counter(){
        count=0;
    }
    public synchronized void run(){
        count++;
    }
    public static void main(String[] args) throws 
    InterruptedException{
        ExecutorService exec=Executors.newFixedThreadPool(2);
        Counter task=new Counter();
        for (int i=0;i<1000;i++ ) {
            exec.execute(task); 
        }
        exec.shutdown();
        exec.awaitTermination(50L,TimeUnit.SECONDS);
        System.out.println(task.count);
    }
}
但我认为在第二个实现中,使用线程是没有意义的,因为执行是顺序的。因为两个线程中只有一个线程具有对象监视器的访问权限,而另一个线程将等待第一个线程的执行,并且只有在第一个线程完成时才具有监视器的访问权限。这听起来像是连续的


如果我错了,请纠正我。非常感谢您的帮助。

使run方法同步有助于避免多线程。它当然会导致顺序处理


请参见

是。非静态方法上的synchronized关键字将给定方法限制为每个实例顺序执行。您只有一个计数器实例,并且正在将其用于所有任务,因此,即使您有一个包含两个线程的线程池,在任何给定时间都只有一个线程在运行。

首先,上面提供的代码仅用于学习案例,这使学习者知道在使用多线程时可能发生的竞争条件,同时知道如何处理竞争条件。在上面提供的代码中,它确实是顺序的,因为synchronized关键字make只有一个线程可以访问块关键部分。考虑到上下文切换时间可以忽略且调度公平,多线程版本的运行时间将大于单线程版本中使用的时间

但是退一步。我们可以从多线程中得到的好处是,我们可以同时执行程序的多个部分。因此,多线程通过多任务处理实现CPU的最大利用率。所以实际上我们需要考虑两种情况。一个是CPU密集型程序,例如代码中的示例。另一种是具有大量I/O或网络绑定处理的程序,这在web应用程序中非常常见

第二个将变得有趣,因为整个过程不是在CPU中发生的

例如,我们有

任务1:2秒从I/O+2秒CPU请求一些数据

task2:2秒从I/O+2秒CPU请求一些数据

如果我们在一个线程中运行,那么总时间将是2s+2s+2s+2s=8秒。 但是如果我们在两个线程中运行,并且假设线程上下文切换将花费1秒,那么实际时间非常快,我们可以忽略

在0处启动->任务1 I/O请求

->task1块和线程上下文更改为task2,taks2在1s开始发出I/O请求

->task2块和线程上下文更改为task1,task1从2秒的IO获取所有数据

->任务2在4s时完成CPU操作

->线程上下文在5s时更改为task2

->任务2在7秒时完成CPU

->结束


考虑到1s上下文切换时间和3个上下文切换3s=7s。这仍然比单线程程序好。

是的,在这里使用线程是无用的。您可能对object及其incrementAndGet方法感兴趣。比…优越。好链接,谢谢