这个问题我一直就不清楚,其实实际的项目中thread用得少,就更不关心拉
可是从前练习的时候也没有显式的synchoronized 这个run()方法啊
为什么是必需呢?有关的文档上就这么谢着,也没说为什么,哪位大虾能够给出一个
较为完整的理论解释啊,附加实例也是不错的
小弟先谢拉

解决方案 »

  1.   

    其实不是必要得, 只是有些特殊情况下特殊得用法有效.
    http://www.yesky.com/20021024/1636648.shtml
      

  2.   

    同意 niko7(掠水无痕) ,同步是当你需要用到同步的时候它就是好东西,不需要的时候你用了就有弊无利了。
      

  3.   

    8.4.3.5 synchronized Methods 
    A synchronized method acquires a lock (§17.1) before it executes. For a class (static) method, the lock associated with the Class object (§20.3) for the method's class is used. For an instance method, the lock associated with this (the object for which the method was invoked) is used. These are the same locks that can be used by the synchronized statement; thus, the code: 
    class Test {
    int count;
    synchronized void bump() { count++; }
    static int classCount;
    static synchronized void classBump() {
    classCount++;
    }
    }
    has exactly the same effect as: 
    class BumpTest {
    int count;
    void bump() {
    synchronized (this) {
    count++;
    }
    }
    static int classCount;
    static void classBump() {
    try {
    synchronized (Class.forName("BumpTest")) {
    classCount++;
    }
    } catch (ClassNotFoundException e) {
    ...
    }
    }
    }
    The more elaborate example: 
    public class Box {
    private Object boxContents;  public synchronized Object get() {
    Object contents = boxContents;
    boxContents = null;
    return contents;
    }  public synchronized boolean put(Object contents) {
    if (boxContents != null)
    return false;
    boxContents = contents;
    return true;
    }
    }
    defines a class which is designed for concurrent use. Each instance of the class Box has an instance variable contents that can hold a reference to any object. You can put an object in a Box by invoking put, which returns false if the box is already full. You can get something out of a Box by invoking get, which returns a null reference if the box is empty. If put and get were not synchronized, and two threads were executing methods for the same instance of Box at the same time, then the code could misbehave. It might, for example, lose track of an object because two invocations to put occurred at the same time. See §17 for more discussion of threads and locks.
      

  4.   

    上面讲的是同步方法。
    下面讲线程和锁
    Threads and Locks 
    While most of the discussion in the preceding chapters is concerned only with the behavior of Java code as executed a single statement or expression at a time, that is, by a single thread, each Java Virtual Machine can support many threads of execution at once. These threads independently execute Java code that operates on Java values and objects residing in a shared main memory. Threads may be supported by having many hardware processors, by time-slicing a single hardware processor, or by time-slicing many hardware processors. Java supports the coding of programs that, though concurrent, still exhibit deterministic behavior, by providing mechanisms for synchronizing the concurrent activity of threads. To synchronize threads, Java uses monitors, which are a high-level mechanism for allowing only one thread at a time to execute a region of code protected by the monitor. The behavior of monitors is explained in terms of locks; there is a lock associated with each object. The synchronized statement (§14.17) performs two special actions relevant only to multithreaded operation: (1) after computing a reference to an object but before executing its body, it locks a lock associated with the object, and (2) after execution of the body has completed, either normally or abruptly, it unlocks that same lock. As a convenience, a method may be declared synchronized; such a method behaves as if its body were contained in a synchronized statement. The methods wait (§20.1.6, §20.1.7, §20.1.8), notify (§20.1.9), and notifyAll (§20.1.10) of class Object support an efficient transfer of control from one thread to another. Rather than simply "spinning" (repeatedly locking and unlocking an object to see whether some internal state has changed), which consumes computational effort, a thread can suspend itself using wait until such time as another thread awakens it using notify. This is especially appropriate in situations where threads have a producer-consumer relationship (actively cooperating on a common goal) rather than a mutual exclusion relationship (trying to avoid conflicts while sharing a common resource). As a thread executes code, it carries out a sequence of actions. A thread may use the value of a variable or assign it a new value. (Other actions include arithmetic operations, conditional tests, and method invocations, but these do not involves variables directly.) If two or more concurrent threads act on a shared variable, there is a possibility that the actions on the variable will produce timing-dependent results. This dependence on timing is inherent in concurrent programming, producing one of the few places in Java where the result of executing a program is not determined solely by this specification. Each thread has a working memory, in which it may keep copies of the values of variables from the main memory that is shared between all threads. To access a shared variable, a thread usually first obtains a lock and flushes its working memory. This guarantees that shared values will be thereafter be loaded from the shared main memory to the threads working memory. When a thread unlocks a lock it guarantees the values it holds in its working memory will be written back to the main memory. This chapter explains the interaction of threads with the main memory, and thus with each other, in terms of certain low-level actions. There are rules about the order in which these actions may occur. These rules impose constraints on any implementation of Java, and a Java programmer may rely on the rules to predict the possible behaviors of a concurrent Java program. The rules do, however, intentionally give the implementer certain freedoms; the intent is to permit certain standard hardware and software techniques that can greatly improve the speed and efficiency of concurrent code. Briefly put, these are the important consequences of the rules: Proper use of synchronization constructs will allow reliable transmission of values or sets of values from one thread to another through shared variables. When a thread uses the value of a variable, the value it obtains is in fact a value stored into the variable by that thread or by some other thread. This is true even if the program does not contain code for proper synchronization. For example, if two threads store references to different objects into the same reference value, the variable will subsequently contain a reference to one object or the other, not a reference to some other object or a corrupted reference value. (There is a special exception for long and double values; see §17.4.) In the absence of explicit synchronization, a Java implementation is free to update the main memory in an order that may be surprising. Therefore the programmer who prefers to avoid surprises should use explicit synchronization.