【问题标题】:Is synchronization better option for multithreading shared resources?对于多线程共享资源,同步是更好的选择吗?
【发布时间】:2015-07-21 04:05:21
【问题描述】:
public class MyResource {

private int count = 0;

void increment() {

    count++;

}

void insert() {    // incrementing shared resource count
    for (int i = 0; i < 100000000; i++) {
        increment();
    }

}

void insert1() {       //incrementing shared resource count
    for (int i = 0; i < 100000000; i++) {
        increment();
    }

}

void startThread() {

    Thread t1 = new Thread(new Runnable() {  //thread incrementing count using insert()

        @Override
        public void run() {
            insert();
        }
    });

    Thread t2 = new Thread(new Runnable() {    //thread incrementing count using insert1()

        @Override
        public void run() {
            insert1();
        }
    });

    t1.start();
    t2.start();

    try {
        t1.join(); //t1 and t2 race to increment count by telling current thread to wait
        t2.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

void entry() {
    long start = System.currentTimeMillis();
    startThread();            //commenting insert(); insert1() gives output as time taken = 452(approx)   110318544  (obvious)

    // insert(); insert1();     //commenting startThread() gives output as time taken = 452(approx)   200000000

    long end = System.currentTimeMillis();
    long time = end - start;
    System.out.println("time taken = " + time);

    System.out.println(count);
}

}

程序入口点来自 entry() 方法。

1.仅使用 insert();插入1(); (普通方法调用)和注释 startThread()(执行线程)给我的结果如代码所示。

2.现在评论 insert();插入1();并使用 startThread()(执行线程)给我结果,如代码所示。

3.现在我同步增量()给我输出的时间 = 35738 200000000

如上所述,同步避免了共享资源的访问,但另一方面需要大量时间来处理。

如果同步会降低性能,那还有什么用呢?

【问题讨论】:

    标签: java multithreading synchronized


    【解决方案1】:

    有时您只想同时进行两件或多件事情。想象一下聊天应用程序的服务器或在长时间任务运行时更新 GUI 以让用户知道处理正在进行的程序

    【讨论】:

    • 两件或多件事情要同时进行,我将使用线程来完成。但是,如果有任何共享资源,我必须使用同步,这会使应用程序变慢......................比为什么要使用同步?。
    • 因为有时候你没有其他选择,所以用性能换取应用需求
    【解决方案2】:

    您不应该使用同步来提高性能,您应该使用它来保护共享资源。 这是一个真实的代码示例吗?因为如果你想在这里使用线程来拆分工作同步

    increment() 
    

    不是最好的方法...

    编辑

    here 所述,您可以更改此特定代码的设计以更有效地在两个线程之间分配工作。 我改变了他们的例子来满足你的需要,但是那里描述的所有方法都很好。

    import java.util.*;
    import java.util.concurrent.*;
    import static java.util.Arrays.asList;
    
    public class Sums {
    
        static class Counter implements Callable<Long> {
    
            private final long _limit;
            Counter(long limit) {
                _limit = limit;
            }
    
            @Override
            public Long call() {
                long counter = 0;
                for (long i = 0; i <= _limit; i++) {
                    counter++
                }
                return counter;
            }                
        }
    
        public static void main(String[] args) throws Exception {
    
            int counter = 0;
            ExecutorService executor = Executors.newFixedThreadPool(2);
            List <Future<Long>> results = executor.invokeAll(asList(
                new Counter(500000), new Counter(500000));
            ));
            executor.shutdown();
    
            for (Future<Long> result : results) {
                counter += result.get();
            }                
        }    
    }
    

    如果你必须使用同步,AtomicLong 会做得更好。

    【讨论】:

    • 我从Cave of Programming得到了这段代码,并被我稍微扭曲以学习同步......我首先尝试通过使用线程来提高性能,但结果出乎意料由于非原子性,所以我尝试同步导致性能非常低的方法.......................最好的方法是什么?
    • @Javed Solkar,编辑了我的答案。
    • 另外,有时您别无选择,只能使用同步。在您发布的示例中,它可能不是最好的方法,但在实际系统中,例如为数百个多线程客户端提供服务的应用程序服务器,并且同步是必须的。
    【解决方案3】:

    性能并不是唯一的因素。正确性也很重要。这是另一个关于关键字synchronized 的低级详细信息的问题。

    如果您正在寻找性能,请考虑使用java.util.concurrent.atomic.AtomicLong 类。它已针对快速、原子访问进行了优化。

    编辑:

    在这个用例中,同步化是多余的。同步对于调用更长且正确性更重要的 FileIO 或 NetworkIO 会更有用。这是AtomicLong 的源代码。之所以选择 Volatile,是因为它对于更改共享内存的短调用具有更高的性能。

    添加 synchronized 关键字会添加额外的 java 字节码,该字节码会检查正确的状态以安全地获取锁。 Volatile 会将数据放在主内存中,这需要更长的访问时间,但 CPU 会强制执行原子访问,而不是 jvm 在后台生成额外代码。

    【讨论】:

    • 好的,但是如果 synchronized 关键字会降低性能并给出正确性,那么它有什么用。
    • 编辑了我的答案来回答你的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    相关资源
    最近更新 更多