thread and share variable

1.share variable

The simplest way for threads to share their results is to use shared variables. They should also use synchronization to ensure that values are propagated correctly from

one thread to another and to prevent threads from seeing inconsistent intermediate results while another thread is updating several related data items.

2.All threads live in the same memory space

As we discussed earlier, threads have a lot in common with processes, except that they share the same process context, including memory, with other threads in the same process. This is a tremendous convenience, but also a significant responsibility. Threads can easily exchange data among themselves simply by accessing shared variables (static or instance fields), but threads must also ensure that they access shared variables in a controlled manner, lest they step on each other's changes.

3.Synchronization for controlled access

The Java language provides two keywords for ensuring that data can be shared between threads in a controlled manner: synchronized and volatile.

Synchronized has two important meanings: it ensures that only one thread executes a protected section of code at one time (mutual exclusion or mutex ), and it ensures
that data changed by one thread is visible to other threads (visibility of changes).鎖的排他性和內存的可見性。

Synchronized 關鍵字,使得某個時間點只有一個線程進入受Synchronized保護的程序塊;並且使得線程工作內存中緩存的共享變量的副本的值失效,當線程進入Synchronized塊時,必須從主內存中load最新的值;當線程退出Synchronized塊時候,必須把緩存中的值刷新到主內存中。

Without synchronization, it is easy for data to be left in an inconsistent state. For example, if one thread is updating two related values (say, the position and velocity
of a particle), and another thread is reading those two values, it is possible that the second thread could be scheduled to run after the first thread has written one value
but not the other, thus seeing one old and one new value. Synchronization allows us to define blocks of code that must run atomically, in which they appear to execute in
an all-or-nothing manner, as far as other threads can tell.The atomic execution or mutual exclusion aspect of synchronization is similar to the concept of critical sections in other operating environments.

4.Volatile關鍵字

Volatile is simpler than synchronization and is suitable only for controlling access to single instances of primitive variables -- integers, booleans, and so on. When
a variable is declared volatile, any write to that variable will go directly to main memory, bypassing the cache, while any read of that variable will come directly from
main memory, bypassing the cache. This means that all threads see the same value for a volatile variable at all times.

注意:Volatile關鍵字只能保證內存的可見性,不能保證原子性操作。

package j.threads;


/**
 * 
 * @author Administrator
 * 該程序總共有21個線程,在主線程中啓動了20個線程,這20個線程分別對共享變量累加1000次,最後得到的結果值
 * 我們期望是20 * 1000 = 20000;但是一旦運行這個程序我們不一定能得到20000.
 * 原因在於volatile只能保證內存的可見性,但是不能保證原子性操作,count++實際上有3個步驟read-modify-write
 * 不是一個獨立的操作。
 *
 */
public class TestVolatile {

private static volatile int count = 0;

private static final int THREAD_COUNTS = 20;

//private static Object lock = new Object();

public static void increase(){
//synchronized(lock){
count++;
//}
}




public static void main(String[] args) throws InterruptedException{
Thread[] threads = new Thread[THREAD_COUNTS];

for(int i = 0; i < THREAD_COUNTS ;i++){
threads[i] = new Thread(new Runnable(){


@Override
public void run() {
for(int j = 0 ; j< 1000;j++)
increase();
}

});

threads[i].start();

}

for(int k = 0 ; k < THREAD_COUNTS; k++){
threads[k].join();
}

System.out.println(count);
}


}

5.對共享變量的複合操作必須要用lock來保證原子性操作。

Volatile is useful for ensuring that each thread sees the most recent value for a variable, but sometimes we need to protect access to larger sections of code, such
as sections that involve updating multiple variables. Synchronization uses the concepts of monitors, or locks, to coordinate access to particular blocks of code.
Every Java object has an associated lock. Java locks can be held by no more than one thread at a time. When a thread enters a synchronized block of code, the thread blocks and waits until the lock is available, acquires the lock when it becomes available, and then executes the block of code. It releases the lock when control exits the protected block of code, either by reaching the end of the block or when an exception is thrown that is not caught within the synchronized block.In this way, only one thread can execute a block protected by a given monitor at one time. The block can be considered atomic because, from the perspective of other threads, it appears to either have executed entirely or not at all.

6.Synchronized blocks

Because synchronization prevents multiple threads from executing a block at once,it has performance implications, even on uniprocessor systems. It is a good practice
to use synchronization around the smallest possible block of code that needs to be protected.

Access to local (stack-based) variables never need to be protected, because they are only accessible from the owning thread.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章