Читаем Programming with POSIX® Threads полностью

This means that the thread that currently has a processor has an advantage. It tends to remain in motion, exhibiting behavior vaguely akin to physical inertia. As a result, you may get away with errors that will cause your code to break in mysterious ways when the newly created or awakened thread is able to run immediately — when there are free processors. The following program, inertia.c, demonstrates how this phenomenon can disrupt your program.

27-41 The question is one of whether the thread function printer_thread will see the value of stringPtr that was set before the call to pthread_create, or the value set after the call to pthread_create. The desired value is "After value." This is a very common class of programming error. Of course, in most cases the problem is less obvious than in this simple example. Often, the variable is uninitialized, not set to some benign value, and the result may be data corruption or a segmentation fault.

39 Now, notice the delay loop. Even on a multiprocessor, this program won't break all the time. The program will usually be able to change stringPtr before the new thread can begin executing — it takes time for a newly created thread to get into your code, after all, and the "window of opportunity" in this particular program is only a few instructions. The loop allows me to demonstrate the problem by delaying the main thread long enough to give the printer thread time to start. If you make this loop long enough, you will see the problem even on a uniprocessor, if main is eventually timesliced.

inertia.c

1 #include

2 #include "errors.h"

3

4 void *printer_thread (void *arg)

5 {

6 char *string = *(char**)arg;

7

8 printf ("%s\n", string);

9 return NULL;

10 }

11

12 int main (int argc, char *argv[])

13 {

14 pthread_t printer_id;

15 char *string_ptr;

16 int i, status; 17

18 #ifdef sun

19 /*

20 * On Solaris 2.5, threads are not timesliced. To ensure

21 * that our two threads can run concurrently, we need to

22 * increase the concurrency level to 2.

23 */

24 DPRINTF (("Setting concurrency level to 2\n"));

25 thr_setconcurrency (2);

26 #endif

27 string_ptr = "Before value";

28 status = pthread_create (

29  &printer_id, NULL, printer_thread, (void*)&string_ptr);

30 if (status != 0)

31  err_abort (status, "Create thread");

32

33 /*

34 * Give the thread a chance to get started if it's going to run

35 * in parallel, but not enough that the current thread is likely

36 * to be timesliced. (This is a tricky balance, and the loop may

37 * need to be adjusted on your system before you can see the bug.)

38 */

39 for (i = 0; i < 10000000; i++);

40

41 string_ptr = "After value";

42 status = pthread_join (printer_id, NULL);

43 if (status != 0)

44  err_abort (status, "Join thread");

45 return 0;

46 }

The way to fix inertia.c is to set the "After value," the one you want the threads to see, before creating the thread. That's not so hard, is it? There may still be a "Before value," whether it is uninitialized storage or a value that was previously used for some other purpose, but the thread you create can't see it. By the memory visibility rules given in Section 3.4, the new thread sees all memory writes that occurred prior to the call into pthread_create. Always design your code so that threads aren't started until after all the resources they need have been created and initialized exactly the way you want the thread to see them.

Never assume that a thread you create will wait for you.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных