Multithreading “一词”的含义是什么;线程安全;?

Multithreading “一词”的含义是什么;线程安全;?,multithreading,language-agnostic,programming-languages,concurrency,Multithreading,Language Agnostic,Programming Languages,Concurrency,这是否意味着两个线程不能同时更改底层数据?或者,这是否意味着当多个线程执行给定的代码段时,该代码段将以可预测的结果运行?线程安全代码是一种即使多个线程同时执行也能工作的代码 线程安全代码按规定工作,即使由不同线程同时输入。这通常意味着,应该不间断运行的内部数据结构或操作会同时受到不同修改的保护。正如其他人所指出的,线程安全性意味着,如果一段代码同时被多个线程使用,那么它将可以正常工作 值得注意的是,这有时需要花费计算机时间和更复杂的编码,因此并不总是可取的。如果一个类只能在一个线程上安全使用,那

这是否意味着两个线程不能同时更改底层数据?或者,这是否意味着当多个线程执行给定的代码段时,该代码段将以可预测的结果运行?

线程安全代码是一种即使多个线程同时执行也能工作的代码


线程安全代码按规定工作,即使由不同线程同时输入。这通常意味着,应该不间断运行的内部数据结构或操作会同时受到不同修改的保护。

正如其他人所指出的,线程安全性意味着,如果一段代码同时被多个线程使用,那么它将可以正常工作

值得注意的是,这有时需要花费计算机时间和更复杂的编码,因此并不总是可取的。如果一个类只能在一个线程上安全使用,那么这样做可能更好


例如,Java有两个几乎等价的类,
StringBuffer
StringBuilder
。区别在于
StringBuffer
是线程安全的,因此
StringBuffer
的一个实例可以同时被多个线程使用
StringBuilder
不是线程安全的,它被设计成一种更高性能的替代品,用于仅由一个线程生成字符串的情况(绝大多数情况)。

不要将线程安全性与确定性混为一谈。线程安全代码也可以是非确定性的。考虑到使用线程代码调试问题的难度,这可能是正常情况。:-)


线程安全只是确保当一个线程修改或读取共享数据时,没有其他线程能够以更改数据的方式访问它。如果代码的正确性取决于特定的执行顺序,那么除了线程安全所需的同步机制之外,还需要其他同步机制来确保这一点。

简单-如果多个线程同时执行此代码,代码将正常运行

是的,是的。这意味着数据不会同时被多个线程修改。但是,您的程序可能会按预期工作,并且看起来是线程安全的,即使它从根本上不是


请注意,结果的不可预测性是“竞争条件”的结果,这可能导致数据被修改的顺序不同于预期的顺序。

要完成其他答案:

当方法中的代码执行以下两项操作之一时,同步只是一个问题:

  • 使用一些非线程安全的外部资源
  • 读取或更改持久对象或类字段
  • 这意味着在方法中定义的变量总是线程安全的。对方法的每次调用都有自己版本的这些变量。如果该方法由另一个线程或同一个线程调用,或者即使该方法调用自身(递归),这些变量的值也不会共享

    线程调度不保证是。一个任务可能完全占用CPU,而以相同优先级的线程为代价。你可以使用Thread.yield()来问心无愧。您可以使用(在java中)Thread.setPriority(Thread.NORM\u PRIORITY-1)来降低线程的优先级

    另外,请注意:

    • 迭代这些“线程安全”结构的应用程序的巨大运行时成本(其他人已经提到)
    • 睡眠(5000)应该睡眠5秒。然而,如果有人改变了系统时间,你可能会睡很长时间或者根本没有时间。操作系统以绝对形式记录唤醒时间,而不是相对形式
    是和否

    线程安全不仅仅是确保共享数据一次只被一个线程访问。您必须确保对共享数据的顺序访问,同时避免、、和


    多线程运行时的不可预测结果不是线程安全代码的必要条件,但它通常是一种副产品。例如,您可以使用共享队列、一个生产者线程和几个消费者线程设置一个方案,并且数据流可能是完全可预测的。如果你开始引入更多的消费者,你会看到更多的随机结果。

    一个更容易理解的方法是,代码不是线程安全的。有两个主要问题会使线程化应用程序产生不需要的行为

    • 访问共享变量而不锁定
      此变量可以在执行函数时由另一个线程修改。您希望通过锁定机制来防止它,以确保函数的行为。一般的经验法则是将锁保持在尽可能短的时间内

    • 共享变量相互依赖导致死锁
      如果您有两个共享变量A和B。在一个函数中,您先锁定A,然后再锁定B。在另一个函数中,您开始锁定B,一段时间后,您锁定A。这是一个潜在的死锁,第一个函数将等待B解锁,而第二个函数将等待A解锁。这个问题可能不会发生在您的开发环境中,而且只是偶尔发生。为了避免这种情况,所有锁的顺序必须始终相同


    我喜欢Brian Goetz的Java并发性实践中的定义,因为它的全面性


    如果一个类在从多个线程访问时行为正确,则该类是线程安全的,而与运行时环境对这些线程执行的调度或交错无关,并且调用代码没有额外的同步或其他协调

    一个信息量更大的问题是,是什么使代码不是线程安全的——答案是,有四个条件必须是真的。。。想象一下下面的代码(以及它的机器语言翻译)

  • 第一个条件是
    totalRequests = totalRequests + 1
    MOV EAX, [totalRequests]   // load memory for tot Requests into register
    INC EAX                    // update register
    MOV [totalRequests], EAX   // store updated value back to memory
    
    class NonThreadSafe {
    
        private int count = 0;
    
        public boolean countTo10() {
            count = count + 1;
            return (count == 10);
        }