Nilai semaphore pada fungsi di dalam fungsi thread tidak konsisten

Saya telah mempelajari cara menggunakan pthreads dan mutex, dan saya bingung dengan keluaran kode C berikut:

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>

void *TestThread(void *);
void TestFunc();

sem_t mutex;

int main(int argc, char *argv[]) {
    pthread_t tid;
    sem_init(&mutex, 1, 0);
    pthread_create(&tid, NULL, TestThread, NULL);
    pthread_join(tid, NULL);
}

void *TestThread(void *arg) {
    int val;
    sem_getvalue(&mutex, &val);
    printf("value of mutex in Thread function: %d\n", val);
    TestFunc();
    pthread_exit(NULL);
}

void TestFunc() {
    int val;
    sem_getvalue(&mutex, &val);
    printf("value of mutex in function in Thread function: %d\n", val);
}

Saya kemudian mengkompilasi ini seperti g++ -lpthread mutexTest.c -o mutexTest dan menjalankannya dengan ./mutexText, yang menghasilkan dan menghasilkan seperti

value of mutex in Thread function: 0
value of mutex in function in Thread function: 1754151134

Mengapa nilai mutex berubah pada fungsi yang saya panggil di dalam thread? Apakah saya kehilangan referensi ke mutex?


person TheStrangeQuark    schedule 12.03.2019    source sumber
comment
Tidak dapat mereproduksi. Bagi saya kodenya terlihat oke.   -  person ggorlen    schedule 13.03.2019
comment
Saya juga belum dapat mereproduksinya, tetapi hanya untuk menghilangkan satu kemungkinan masalah, coba sem_init(&mutex, 0, 0);. Jika hal ini mengubah perilaku, beri tahu kami.   -  person thb    schedule 13.03.2019
comment
apa yang terjadi jika Anda mengkompilasi dengan kompiler C, seperti gcc, bukan kompiler C++?   -  person bruceg    schedule 13.03.2019
comment
@thb Melakukan perubahan itu memberikan hasil yang sama   -  person TheStrangeQuark    schedule 13.03.2019
comment
@bruceg Kompilasi dengan gcc menghasilkan hasil yang sama   -  person TheStrangeQuark    schedule 13.03.2019
comment
+1 Saya melihat tidak ada potensi masalah lainnya. Menarik. Seperti Anda, saya akan senang membaca jawabannya ketika sudah muncul.   -  person thb    schedule 13.03.2019
comment
Sistem operasi dan versi gcc apa yang Anda gunakan?   -  person bruceg    schedule 13.03.2019
comment
@bruceg MacOS Mojave 10.14.2, gcc dan g++ keduanya mengatakan Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 10.0.0 (clang-1000.10.44.4) Target: x86_64-apple-darwin18.2.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin   -  person TheStrangeQuark    schedule 13.03.2019
comment
ya... di MacOS gcc dan g++ keduanya merupakan alias untuk rangkaian kompiler Mac. Saya tidak dapat melakukan repro di kotak linux saya. Semoga orang lain memiliki Mac.   -  person bruceg    schedule 13.03.2019
comment
Apa yang sem_getvalue() kembalikan dalam kedua kasus tersebut? Jika hasilnya bukan nol, apa itu errno? sem_getvalue() di Mac sepertinya merepotkan. Lihat stackoverflow.com/questions/ 16655153/ dan stackoverflow.com/questions/23146950/   -  person Andrew Henle    schedule 13.03.2019
comment
@AndrewHenle Ide bagus. Ini mengembalikan -1 dan errno diatur ke 78 dalam kedua kasus. Tampaknya ini berarti fungsinya tidak disetel. Menarik.   -  person TheStrangeQuark    schedule 13.03.2019
comment
@TheStrangeQuark Saat mengkompilasi dengan gcc atau clang, Anda harus selalu menggunakan opsi -Wall.   -  person user3386109    schedule 13.03.2019
comment
Sebagai informasi, di mesin saya (Debian GNU/Linux 9, GCC 6.3, Pthreads 2.24), ia mengembalikan 0 dan errno disetel ke 0 dalam kedua kasus tersebut. Sebagai informasi juga, saya mengkompilasi dengan -Wall dan, tentu saja, juga dengan -Wextra -Werror.   -  person thb    schedule 13.03.2019
comment
Jika Anda benar-benar membutuhkan mutex (bukan semaphore penghitungan), lihat pthread_mutex_create, pthread_mutex_lock dan pthread_mutex_unlock.   -  person user3386109    schedule 13.03.2019
comment
Menjalankan ini di Linux berfungsi dengan baik. @ user3386109 benar karena sudah tidak digunakan lagi dan saya tidak boleh menggunakannya. Terimakasih semuanya   -  person TheStrangeQuark    schedule 13.03.2019


Jawaban (1)


Saya tidak tahu mengapa kode Anda gagal. Sayangnya untuk tujuan kita saat ini, kode Anda berhasil di mesin saya.

Sampai orang lain memposting jawaban yang tepat, jika Anda ingin mencoba beberapa ide debugging dengan saya, sesuai pilihan Anda, kita dapat mencoba yang berikut ini.

1. Coba saran dari @AndrewHenle: "Apa yang sem_getvalue() kembalikan dalam kedua kasus? Jika hasilnya bukan nol, apa itu errno?"

Sebagai informasi, di mesin saya (Debian GNU/Linux 9, GCC 6.3, Pthreads 2.24), ia mengembalikan nol dan errno juga nol.

2. Coba ubah

sem_t mutex;

to

volatile unsigned char buffer_before_mutex[0x1000];
sem_t mutex;
volatile unsigned char buffer_after_mutex[0x1000];

Alasan: jika ada sesuatu yang menimpa mutex Anda di tumpukan, ini mungkin memberinya ruang kosong untuk ditimpa alih-alih membuang mutex tersebut. Sekalipun ini berhasil (dan saya kira tidak akan berhasil), itu tidak benar; tetapi ini mungkin memberikan petunjuk tentang apa yang salah dengan kode Anda.

3. (Jawaban saya mungkin digantikan oleh komentar. Saya tinggalkan jawabannya di sini kalau-kalau ada bagian yang terbukti berguna.)

person thb    schedule 13.03.2019
comment
Apa yang tidak diperhatikan oleh OP adalah bahwa sem_init dan sem_getvalue tidak digunakan lagi di MacOS. Mengompilasi dengan -Wall akan membuatnya sangat jelas. Fungsinya hanyalah stub yang menyetel errno dan kembali. - person user3386109; 13.03.2019