Solving multithreading concurrency problems

Source: Internet
Author: User
Tags commit flock memory usage mutex object serialization serialization string back
1. File Lock

If the table is updated or inserted into the operation, it will go through a unified file, this way is a multi-process concurrency can be resolved problem;

Here's how it's implemented:

public static function Cbinventoryreserve () {
        $LOCK _file_path = $_server[' Document_root ']. " Wmsinventoryapi/inventory/inventoryreserve.php ";
        $fp = fopen ($LOCK _file_path, "R");
        if (! $fp) {die
            ("Failed to open the lock file!");
        }
        Flock ($FP, lock_ex);
        
    Action required
        $params = Flight::request ()->getbody ();
        $params = Json_decode ($params, true);
        if (! Is_array ($params) | | empty ($params)) {
            Flight::sendrouteresult (Array ("error_code" = "40002", "Error_ Info "=" params Empty "));
        $result = \inventory\inventoryengine::getinstance ()->inventoryreserve ($params);
        
        Flock ($FP, lock_un);
        Fclose ($FP);
        Flight::sendrouteresult ($result);
    }

The function description flock () does various locking or unlocking actions on the file that the parameter FD refers to in the manner specified by the parameter operation. This function locks only the entire file and cannot lock a region of the file.

The parameter operation has the following four conditions:

Lock_sh establish a shared lock. Multiple processes can share a lock on the same file at the same time.

LOCK_EX establish a mutex lock. A file has only one mutex lock at a time.

Lock_un unlocks the file lock status.

LOCK_NB unable to establish a lock, this operation is not blocked and will return to the process immediately. Usually do or with Lock_sh or LOCK_EX (|) Combination.

A single file cannot establish both shared and mutex locks, and the file descriptor does not inherit this lock when using DUP () or fork ().

The return value returns 0 for success, and returns 1 if there is an error, and the error code is stored in errno.

In other words:

With shared lock lock_sh, if it is read, it does not need to wait, but if it is written, it needs to wait for the read to complete.

With exclusive lock LOCK_EX, both write/Read waits.

Lock_un, the use of shared/read take-up locks, you need to unlock when finished.

LOCK_NB, when locked, does not block, but prompts for locking.

For better portability, the opening and closing of files I chose the combination of fopen and fclose, but the first parameter of flock required a file descriptor of type int. The file pointer returned by fopen is converted to the file descriptor of type int (assuming that the file descriptor returned by the Open function is FD, and fopen returns the file pointer *fp, FD is equivalent to Fp->_fileno). 2. Serialization of Interfaces (object serialization)

All values in PHP can be represented by using the function serialize () to return a string containing a stream of bytes. The Unserialize () function can re-change the string back to the original PHP value. Serializing an object saves all variables of the object, but does not save the object's methods, only the name of the class is saved.

<?php
//classa.inc:
  
  class A {public
      $one = 1;
    
      Public Function Show_one () {
          echo $this->one;
      }
  }
  
page1.php:

  include ("Classa.inc");
  
  $a = new A;
  $s = serialize ($a);
  Save the variable $s so that the file page2.php can read
  file_put_contents (' store ', $s);

page2.php:
  
  //To properly understand serialization, you must include the following file
  include ("Classa.inc");

  $s = file_get_contents (' store ');
  $a = unserialize ($s);

  You can now use the function Show_one () inside the object $ A ()
  $a->show_one ();
? >
3. SELECT * * * * FOR UPDATE

Select ... for The update statement is a manual lock statement that we often use. Typically, the SELECT statement does not lock the data, preventing other DML and DDL operations from being affected. Also, with the support of the multi-version consistent-read mechanism, the SELECT statement is not hindered by other types of statements.

With the FOR UPDATE clause, we can manually implement the data lock protection operation at the application level.

The default behavior of the FOR UPDATE clause is to automatically start a transaction and lock the data with the lock mechanism of the transaction.

To open a transaction using the for update

Start transaction;

Select sum (quantity) from the Ws_inventory_item where inventory_item_id=86 for update;

When another transaction is opened, the update operation can only wait for the above transaction and commit to execute;

Start transaction;

Update Ws_inventory_item Set quantity = quantity + 1  where inventory_item_id = 86;
MySQL uses SELECT ... The for UPDATE confirms before the transaction is writtenWith MySQL InnoDB as an example, the preset tansaction isolation level is repeatable read and the read lock in SELECT is divided into two main ways:
SELECT ... LOCK in SHARE MODE
SELECT ... For UPDATE
Both of these methods must wait for the other transaction data to be committed (commit) when the transaction (Transaction) is in between select and the same data table. The main difference is that lock in SHARE MODE is prone to deadlock when one of the transactions is to update the same form. Simply put, if you want to update the same form after select, it's best to use Select ... UPDATE. For example, suppose that the product list contains a quantity of the number of items in the product, before the order is established, it is necessary to determine whether the quantity is sufficient (quantity>0) before the quantity is updated to 1. Unsafe practices:
SELECT Quantity from Products WHERE id=3;
UPDATE products SET quantity = 1 WHERE id=3;
Why it's not safe. A small number of situations may not be a problem, but a lot of data access "definitely" will be problematic. If we need to quantity>0 in the case of inventory, assuming that the program in the first SELECT read to the quantity is 2, it seems that the number is not wrong, but when MySQL is ready to update, there may have been the inventory has been deducted 0, but the program is unaware I don't know, will Wrong's UPDATE went down. Therefore, the transaction mechanism must be through to ensure that the data read and submitted are correct. So we can test it in MySQL: (note 1)
1    SET autocommit=0;
2    BEGIN work;
3    SELECT quantity from Products WHERE id=3 for UPDATE;
Id=3 data in the products data is locked (note 3), other transactions must wait for the transaction to be committed before the SELECT * from the products where id=3 for UPDATE (note 2) so as to ensure that quantity in other transactions The number read is correct.
1    UPDATE Products SET quantity = ' 1 ' WHERE id=3;
2    COMMIT work;
Commit (Commit) write to database, products unlock. Note 1:begin/commit is the starting and ending point of a transaction, you can use more than two MySQL Command windows to interactively observe the condition of the lock. Note 2: In the midst of a transaction, only select ... For UPDATE or lock in SHARE MODE the same pen data will wait for other transactions to finish before executing, general Select ... is not affected by this. Note 3: Because the InnoDB preset is row-level lock, data column locking can refer to this article.   Note 4:innodb form try not to use the lock TABLES instructions, if the situation must be used, please first look at the official InnoDB use lock TABLES instructions, so as not to cause the system often deadlock. MySQL SELECT ... The for UPDATE's Row lock and Table lock above are described in select ... The use of for UPDATE, but the lock data is a discriminant, you have to pay attention to. Because the InnoDB preset is Row-level lock, only the "explicitly" specified primary key, MySQL will execute Row lock (only lock the selected data), otherwise MySQL will execute table lock (the entire data form to lock). For example: Suppose there is a form products with ID and name two fields, ID is the primary key. Example 1: (explicitly specifying a primary key and having this data, row lock)
     SELECT * FROM Products WHERE id= ' 3 ' for UPDATE;
Example 2: (explicitly specify the primary key, if the data is not found, no lock)
     SELECT * FROM Products WHERE id= '-1 ' for UPDATE;
Example 2: (No primary key, table lock)
     SELECT * FROM Products WHERE name= ' Mouse ' for UPDATE;
Example 3: (primary key ambiguous, table lock)
     SELECT * FROM Products WHERE id<> ' 3 ' for UPDATE;
Example 4: (primary key ambiguous, table lock)
     SELECT * from the products WHERE ID like ' 3 ' for UPDATE;
Note 1:for UPDATE applies only to InnoDB and must be in the transaction block (Begin/commit) to take effect. NOTE 2: To test the condition of the lock, you can use the command Mode of MySQL and open two windows to do the test. 4. Transaction ISOLATION LEVEL

How to troubleshoot multiple-process or multi-threaded concurrency problems

Reproduced in this section, original address: http://singo107.iteye.com/blog/1175084

There are 4 isolation levels for database transactions, from low to high to read uncommitted, Read committed, Repeatable read, and Serializable, which can solve the problems of dirty reading, non-repeatable reading, and Phantom reading one by one.

√: May appear x: does not appear

Dirty Read Non-REPEATABLE READ Phantom reading
Read UNCOMMITTED
Read committed X
REPEATABLE READ X X
Serializable X X X

Note: We discuss the isolation level scenario, mainly in the case of multiple transactions concurrency, so the next explanation is around the transaction concurrency. READ UNCOMMITTED not submitted

The company paid, the leader of the 5000 yuan to the Singo account, but the transaction did not submit, and Singo just to check the account, found that the salary has been to the account, is 5000 yuan whole, very happy. Unfortunately, the leadership found that the amount of wages issued to Singo is not correct, is 2000 yuan, and then quickly rolled back to business, modify the amount, the transaction will be submitted, and finally singo the actual salary of only 2000 yuan, Singo empty joy a game.



The above situation, that is what we call dirty Read, two concurrent transactions, "transaction A: lead to Singo payroll", "Transaction B:singo query Payroll account", transaction B read the transaction A has not yet committed data.

When the isolation level is set to read UNCOMMITTED, dirty reads can occur and how to avoid dirty reads, see the next isolation level. Read Committed reading commit

Singo take the payroll card to spend, the system read to Cary really have 2000 yuan, and at this time her wife also just in the online transfer, the Singo Pay card of 2000 yuan to another account, and before Singo submitted the business, when Singo deduction, System Check to Singo's payroll card has no money, deduction failure, Singo very puzzled, obviously card money, why ...

The above situation, that is what we call non-repeatable read, two concurrent transactions, "transaction A:singo consumption", "Transaction B:singo wife online transfer", transaction A in advance read the data, transaction B immediately updated the data, and committed the transaction, and transaction a read the data again, The data has changed.

When the isolation level is set to read Committed, dirty reads are avoided, but may cause non-repeatable reads.

The default level for most databases is read committed, such as SQL Server, Oracle. To resolve the issue of non-repeatable reads, see the next isolation level. Repeatable READ Repeat

You can avoid non-repeatable reads when the isolation level is set to repeatable read. When Singo took the payroll card to spend, once the system began to read the Payroll card information (that is, the start of the transaction), Singo's wife could not change the record, that is Singo wife can not be transferred at this time.

Although repeatable read avoids non-repeatable reads, it is possible to have phantom reads.

Singo's wife works in the banking department, and she often views Singo's credit card consumption records through the internal banking system. One day, she was inquiring into the total consumption amount of credit card in Singo month (select SUM (amount) from transaction where month = this month) was $80, and Singo at this time was good to eat outside the sea plug at the cashier to pay, spend 1000 yuan , which adds a $1000 consumption record (insert transaction ... ), and submitted a transaction, then Singo's wife will singo the current month credit card consumption details printed to A4 paper, but found that the total consumption of 1080 yuan, Singo wife is very surprised, thought there was an illusion, the illusion of such a generation.

Note: The default isolation level for MySQL is repeatable read. Serialization of Serializable

Serializable is the highest transaction isolation level, with the highest cost and low performance, which is rarely used at this level, where the transaction sequence executes not only to avoid dirty reads, non-repeatable reads, but also to avoid Phantom reads. how MySQL Transaction isolation level is set

The user can use the SET TRANSACTION statement to change the isolation level of a single session or all new incoming connections. Its syntax is as follows:

SET [SESSION | GLOBAL] TRANSACTION Isolation Level {READ UNCOMMITTED | READ COMMITTED | Repeatable READ | SERIALIZABLE}

Note: The default behavior (without session and global) is to set the isolation level for the next (not started) transaction. If you use the Global keyword, the statement sets the default transaction level globally for all new connections created from that point, except for connections that do not exist. You need super privilege to do this. Use the session keyword to set the default transaction level for future transactions performed on the current connection. Any client can freely change the session isolation level (even in the middle of a transaction) or set the isolation level for the next transaction.

Java Multi-threaded concurrent programming will have many different problems, the main problem is the following applications: Multi-threaded read-write shared data synchronization problem concurrent reading data, maintaining the data consistency of each thread read.  Solution: synchronized keyword and lock concurrency lock: mainly to solve the multi-threaded shared data synchronization problem.   Threadlocal mainly solves the problem that the data in multi-threading is inconsistent due to concurrency. threadlocal and synchronized have essential differences: synchronized is the mechanism by which a lock is used, so that a variable or block of code can be accessed by only one thread at a time. Instead, Threadlocal provides a copy of the variable for each thread, so that each thread accesses the same object at a certain time, isolating data sharing from multiple threads. Threadlocal and synchronized have essential differences: synchronized is the mechanism by which a lock is used, so that a variable or block of code can be accessed by only one thread at a time. Instead, Threadlocal provides a copy of the variable for each thread, so that each thread accesses the same object at a certain time, isolating data sharing from multiple threads. Synchronized, in contrast, is used to gain data sharing when communicating between multiple threads.
Threadlocal and synchronized have essential differences: synchronized is the mechanism by which a lock is used, so that a variable or block of code can be accessed by only one thread at a time. Instead, Threadlocal provides a copy of the variable for each thread, so that each thread accesses the same object at a certain time, isolating data sharing from multiple threads. Synchronized, in contrast, is used to gain data sharing when communicating between multiple threads.

What is threadlocal.

As early as the version of JDK 1.2, Java.lang.threadlocal,threadlocal provides a new way to solve the concurrency problem of multi-threaded threads. Using this tool class, you can write beautiful multithreaded programs very concisely.

Threadlocal is easy to words too literally, assuming it is a "local thread". In fact, threadlocal is not a thread, but a local variable of thread, perhaps naming it as threadlocalvariable is easier to understand.

When you use threadlocal to maintain variables, Threadlocal provides a separate copy of the variable for each thread that uses the variable, so each thread can independently change its own copy without affecting the copy of the other thread.

From the thread's point of view, the target variable is like a thread's local variable, which is the meaning of the "local" in the class name.

Thread-local variables are not a new Java invention, and many languages (such as IBM IBM XL FORTRAN) provide thread-local variables at the syntactic level. There is no language-level support in Java, but rather a disguised way to provide support through the Threadlocal class.

Therefore, the code to write thread-local variables in Java is relatively clumsy, resulting in thread-local variables not being well-popularized in Java developers.

interface method for Threadlocal

Threadlocal class interface is very simple, there are only 4 methods, let us first look at:

void set (Object value)
Sets the value of the thread local variable for the current thread.

Public Object Get ()
This method returns the thread local variable that corresponds to the current thread.

public void Remove ()
Removes the value of the current thread local variable to reduce memory usage, which is a new method of JDK 5.0. It is important to note that when the thread ends, the local variables of the thread that should be used are automatically garbage collected, so it is not necessary to explicitly call the method to clear the thread's local variables, but it can speed up the memory reclamation.

Protected Object InitialValue ()
Returns the initial value of the thread's local variable, which is a protected method, apparently designed for subclasses to overwrite. This method is a deferred call method that executes only when the thread calls get () or set (Object) for the 1th time, and executes only 1 times. The default implementation in Threadlocal returns a null directly.

It is worth mentioning that, in JDK5.0, Threadlocal already supports generics, and the class name of the class has become threadlocal<t>. The API methods are also adjusted accordingly, and the new version of the API method is void set (t value), t get (), and T InitialValue ().

Threadlocal is how to maintain a copy of a variable for each thread. The idea is simple: there is a map in the Threadlocal class that stores a copy of the variable for each thread, the key for the element in the map is the thread object, and the value corresponds to the variable copy of the thread. We can provide a simple implementation version by ourselves:

  <span style= "FONT-SIZE:18PX;" >//  Code Listing 1 simplethreadlocal   class simplethreadlocal {        private map valuemap = collections.synchronizedmap (New HashMap ());        public void set (object newvalue)  {            valuemap.put (Thread.CurrentThread (),  newvalue); The// ① key is a thread object, Variable copy with value of this thread        }       public object get ()  {           Thread currentThread =  Thread.CurrentThread ();           Object o =  Valuemap.get (CurrentThread);// ② returns the variable that corresponds to this thread            if   (O == null && !valuemap.containskey (currentthrEAD)  {// ③ If it does not exist in the map, put it in map              Saved in   // .                o = initialvalue ();               valuemap.put ( Currentthread, o);           }            return o;       }        public void remove ()  {            valuemap.remove (Thread.CurrentThread ());       }        public object initialvalue ()  {            return null;       }  }</span>  

Although the code listing 9?3 this threadlocal implementation version seems naïve, it is similar to the Threadlocal class provided by the JDK in the implementation.

A theadlocal instance
<span style= "FONT-SIZE:18PX;" >package threadLocalDemo;   public class sequencenumber {        // ① threadlocal InitialValue () method with Anonymous inner class override, specify initial value         Private static threadlocal<integer> seqnum = new threadlocal<integer > ()  {           public integer initialvalue ()  {               return 0;            }       };        // ② Get Next sequence value        public int  Getnextnum ()  {           seqnum.set (Seqnum.get ()  +  1);           return seqnum.get ();        }       public static void main ( String[] args)        {            sequencenumber sn = new sequencenumber ();            // ③ 3 threads sharing SN, each generating serial number             Testclient t1 = new testclient (SN);            testclient t2 = new testclient (SN);            testclient t3 = new testclient (SN);            t1.start ();           t2.start ();            t3.start ();       }    &Nbsp;   private static class testclient extends thread       {           private  sequencenumber sn;           public testclient ( SEQUENCENUMBER&NBSP;SN)  {                this.sn = sn;           }            public void run ()             {                for  (int i = 0; i < 3; i++)  {                    // ④ 3 sequential values per thread         &nbsP;          system.out.println ("thread["  +  Thread.CurrentThread (). GetName () + "] sn["  + sn.getnextnum ()  +  "]");                }            }       }  }</span>  

References: http://www.xuebuyuan.com/1628079.html http://blog.sina.com.cn/s/blog_5204918b0100d044.html Threadlocal and synchronized have essential differences: synchronized is the mechanism by which a lock is used, so that a variable or block of code can be accessed by only one thread at a time. Instead, Threadlocal provides a copy of the variable for each thread, so that each thread accesses the same object at a certain time, isolating data sharing from multiple threads. Synchronized, in contrast, is used to gain data sharing when communicating between multiple threads.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.