As mentioned earlier, the biggest hidden danger of lazy list is logical deletion, but there is no physical deletion problem. Therefore, EBR first solve d this problem to him.
I EBR modification
int parse_delete(intset_l_t *set, val_t val) { node_l_t *pred, *curr; int result, validated, isVal; while(1) { //Init pred = set->head; curr = get_unmarked_ref(pred->next); //Unmark and lock each node while (curr->val < val) { pred = curr; curr = get_unmarked_ref(curr->next); } LOCK(&pred->lock); LOCK(&curr->lock); /* * Mark Phase: * Start from the root set to find all memory block references, and then mark the referenced memory block (mark) */ //check its validated and curr->val whether equals val validated = parse_validate(pred, curr); isVal = val == curr->val; result = validated && isVal; //only meeting at same time, make pred->next = newnode if (result) { curr->next = get_marked_ref(curr->next); pred->next = get_unmarked_ref(curr->next); } //UNLOCK curr and pred UNLOCK(&curr->lock); UNLOCK(&pred->lock); /* * Sweep Phase: * All memory blocks that are not marked are considered garbage and can be recycled */ //find memory blocks that are not marked, setting a mark bit to 1 result = result && parse_find(curr,isVal); //wait until pred and curr meet the validate conditions, exit this loop if(validated){ //free the element free(curr); return result; } } }
II Performance comparison before and after
original:
unsafe:
In the original version, 2 threads complete from 1 to 10 readings, while in the unsafe version, 5 threads get 50 jobs, and the terminal display time is almost the same.
Compared with the past, the existing performance has the following advantages.
Firstly, the efficiency of the program is greatly improved, and the advantages of multi-core CPU are really brought into play to make full use of CPU. Then, it can prevent blocking and promote the establishment of the whole program model. It is very suitable for multiple identical threads to process the same resource. Moreover, synchronous collection is much faster and more flexible than before.
III Constructing artificial environment reflects insecurity
As mentioned earlier, after the change, it is an unsafe version, so where is the unsafe version?
When counting, single thread may be correct, but multi-threaded error
Because a multithreaded operation will only see its current thread, the order of changing variables is not fixed.
Here we use java multithreading to show the results
public class jthread { public static void main(String[] args) { //Test 3 people in multithread condition WebTickets w = new WebTickets(); Thread t = new Thread(w,"Alan"); t.start(); Thread t1 = new Thread(w,"Mike"); t1.start(); Thread t2 = new Thread(w,"Jay"); t2.start(); } } class WebTickets extends Thread{ private int ticketNums = 99; // from ticket = 99 to 0, 3 people buy these tickets public void run(){ while(true) { //when ticket<=0, stop if(ticketNums<=0) { break; } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //sout the consquence System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--); } } }
As shown in the figure, the ticket grabbing applet written in java can't stop and grab tickets below 0.
Therefore, the implementation of synchronization mechanism needs to pay attention to the following points: high security, low performance, multi-threaded use. High performance, low security, for single thread.
- Do not synchronize all methods of the thread safe class, only those that change the shared resources.
class WebTickets implements Runnable{ //create static key static Object str = "str"; //Random value private int ticketNums = 99; // from ticket = 99 to 0, 3 people buy these tickets @Override public void run(){ while(true) { //when ticket<=0, stop synchronized(str){ //use lock if(ticketNums<=0) { break; } try { Thread.sleep(200);//rest 0.2 seconds } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--); } } } }
2. If the variable class has two running environments, in the threaded environment and multithreaded environment, the variable class should have two versions: thread safe version and thread unsafe Version (without synchronization method and synchronization block). In a single threaded environment, the thread unsafe version is used to ensure performance, and the thread safe version is used for multithreading.