Linux time functions have their special usage methods. This is easy to ignore in engineering projects. In this article, we will make a summary of the use of time functions in multithreading.
First, take a look at a function and remove the one-day function. This function uses the time function localtime or localtime_r to obtain the system time.
Int getnexttime (INT curtm)
{
Struct tm t;
T. tm_year = curtm/10000-1900;
T. tm_mon = (curtm/100) % 100-1 );
T. tm_mday = (curtm) %100;
T. tm_hour = 1;
T. tm_min = 0;
T. tm_sec = 0;
Time_t NT;
// Struct TM * local;
Struct TM local;
Char Buf [16];
Nt = mktime (& T) + 24*3600;
// Local = localtime (& NT); // ------------------ (1)
Localtime_r (& nt, & local); // ------------------ (2)
Sprintf (BUF, "% 4D % 02d % 02d % 02d % 02d", local. tm_year + 1900, local. tm_mon + 1, local. tm_mday, 0 );
Return (INT) (ATOL (BUF)/1000000 );
}
Then, encapsulate the function in the Thread class to facilitate the testing of multithreading using the time function localtime or localtime_r.
Class mythread: Public thread
{
Public:
Mythread (): m_isrun (false ){}
Virtual void run ()
{
Int beginin = 19860101;
Int end = 20130104;
Int COUNT = 0;
Int cur = begin;
Int next;
While (cur! = End)
{
Next = getnexttime (cur );
Count ++;
Cur = next;
}
If (count! = 9865) // 19860101-20130104 theoretically has a total of 9865 days. If multiple threads do not calculate it, print it out.
Cout <count <Endl;
}
Virtual void stop () {m_isrun = true ;}
Virtual ~ Mythread (){}
PRIVATE:
Bool m_isrun;
};
Test:
Void threadtest ()
{
For (int K = 0; k <20; k ++)
{
Mythread P [30];
For (INT I = 1; I <30; I ++)
P [I]. Start ();
For (INT I = 1; I <30; I ++)
P [I]. Join ();
For (INT I = 1; I <30; I ++)
P [I]. Stop ();
Cout <"the" <k <"test end! "<Endl;
}
}
The result shows that if the time function uses (1), the number of incorrect count is returned when multiple threads are called, and the value of (2) is correct. Therefore, in Linux time functions --
The localtime function can only be used in a single thread, while localtime_r should be used in multiple threads. The latter is a thread-safe time function.
Is mktime, localtime_r, and gettimeofday thread-safe?
From: http://hi.baidu.com/pkuyikai/item/aad084ca252966d797445246
Previously, in order to diagnose problems in the system's retrieval performance, the program was timing in stages and the diagnosis result was: the more records, the longer the time consumed by these three stages. Review the main work code in three phases repeatedly, but finds that the Code cannot be so time-consuming. Slowly, time consumption occurs in the mktime () method. Therefore, we suspect that the mktime () method and the localtime_r () method are not thread-safe. But these methods are also used in other projects. Why didn't they find such a problem?
In the document description of glibc, glibc provides a thread-safe method localtime_r to replace localtime. Mktime does not have a thread unsafe problem. Therefore, according to the glibc document, localtime_r and mktime can be safely used in a multi-threaded environment. This is not the case in reality. Find the source code of mktime () and localtime_r (), and finally find the secret.
Mktime and localtime_r both take into account the time zone conversion, while the global variable tzname/timezone/daylight is used for time zone calculation. This is essentially thread-safe.
By analyzing the source code of these two system functions in glibc, we can know that there are two problems in their implementation:
1. The static variable is_initialized used in tzset_internal
2. The global variable tzname/timezone/daylight must be rewritten for mktime each time.
Therefore, mktime and localtime_r are not suitable for multithreading applications.
Solution 2:
1. Implement mktime and localtime_r by yourself. However, it is troublesome to calculate the time zone. Of course, you can also choose not to use the time zone information or use a fixed time zone, such as the Beijing time zone. This is much easier. Because the company's servers basically do not have time zone problems, we have implemented these two methods by ourselves.
2. Use the mutex of pthread to lock mktime and localtime_r, but the pthread library is not good at portability.
Gettimeofday () syscall is used to obtain the current time information in the timeval format (accurate to microseconds) and the current timezone of the system ). The pointer parameter TV of the Structure Type timeval points to the user space buffer that receives the time information. The parameter tz Is a pointer of the timezone structure type and points to the user space buffer that receives the time zone information. Both parameters are output parameters. The return value 0 indicates success, and the Return Value Negative indicates an error.
First, let's take a look at the spin_lock mechanism. The spin_lock mechanism and the semaphore mechanism solve the mutual exclusion problem between two processes. They both allow one process to exit the critical section and the other process to enter. However, the sempahore mechanism allows the process to temporarily exit the CPU, enter the waiting queue waiting policy, while the implementation of the spin_lock is but the process is idling, waiting for another process to end.
In the gettimeofday () code, values (lock, flags), read_lock_irq (LOCK), read_lock_bh (LOCK), write_lock_irqsave (lock, flags), write_lock_irq (LOCK), write_lock_bh (LOCK) all are a small variant of the spin_lock, while the method used by the spin_lock is to run one process, and the other process is busy waiting, because there is only one CPU machine (up) on the micro level, only one process is running. Therefore, gettimeofday () is not a thread-Safe System Call.