使用同步会使此代码按顺序进行吗?

我是线程池的新手,正在学习使用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;
    }
    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);
    }
}

但是我认为在第二种实现中,没有必要使用线程,因为执行将是“顺序的”。因为两个线程中只有一个线程可以访问对象监视器,而另一个线程将等待直到执行第一个线程,并且仅在第一个线程完成后才是监视器的访问权限。这听起来像是连续的。

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

niaoren123456ZJJ1988 回答:使用同步会使此代码按顺序进行吗?

是的。非静态方法上的synced关键字将给定方法限制为按实例顺序执行。您只有一个Counter实例,并且正在为所有任务重用它,因此,即使您有一个带有2个线程的线程池,在任何给定时间也只有一个在执行run()。

,

使run()方法同步是一种使多线程无效的方法。当然会导致顺序处理

请参阅Should you synchronize the run method? Why or why not?

,

首先,上面提供的代码仅用于学习案例,这使学习者了解使用多线程时可能发生的竞争条件,以及如何照顾竞争条件。在上面提供的代码中,由于使用了同步关键字,使得只有一个线程可以访问该块(关键部分),因此它确实是顺序的。考虑到上下文切换时间可以忽略不计且安排合理,因此多线程版本的运行时间将大于一个线程版本中的时间。

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

第二个将变得有趣,因为整个过程并未在CPU中发生。

例如,我们有

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

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

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

开始-> task1 I / O请求为0

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

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

-> task2在4s内完成CPU操作

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

-> task2在7s处完成CPU。

->结束

考虑1s上下文切换时间,而3个上下文切换(3 s)= 7s。还是比单线程程序更好。

本文链接:https://www.f2er.com/3132480.html

大家都在问