C 学习记录-结构体与多线程/互斥锁

一,结构体

结构也是一种数据类型,他是由基本数据类型构成的、并用一个标志符来命名的各种变量的组合;

struct 结构名
{
    类型 变量名;
    类型 变量名;
    ...
}结构变量;

结构名是结构的标志符,不是变量名;

struct string
     {
          char name[8];

          int age;

          char sex[2];

          char depart[20];

          float wage1, wage2, wage3, wage4, wage5;

     } person;

第二种:
struct string
     {
          char name[8];

          int age;

          char sex[2];

          char depart[20];

          float wage1, wage2, wage3, wage4, wage5;

     };

     struct string person;
第三种:无名结构
struct
     {
          char name[8];

          int age;

          char sex[2];

          char depart[20];

          float wage1, wage2, wage3, wage4, wage5;

     } person;

联合体
使几个不同类型的变量共占一段内存(相互覆盖)
声明一个联合体:
union abc{
    int i;
    char m;
}
1,在联合体abc中,整型量i和字符m公用同一内存位置;
2,当一个联合被说明时,编译程序自动的产生一个变量,其长度为联合中最大的变量长度



===============================================
结构体变量所占内存长度是各成员占的内存长度的总和。
联合体变量所占内存长度是各最长的成员占的内存长度。
联合体每次只能存放哪个的一种。
联合体变量中起作用的成员是最后一次存放的成员,在存入新的成员后原有的成员失去了作用。

===============================================


二, 引申学习多线程编程,互斥锁

互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源,可以保证以下三点:
    原子性:把一个互斥量锁定为一个原子操作,这意味着操作系统保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量。
    唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量。
    非繁忙等待:如果一个线程可以锁定一个互斥量,第二个线程有试图去锁定这个互斥量,则第二个线程将被挂起,直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。

头文件:pthread.h
初始化互斥锁:
函数原型:int pthread_mutex_init(pthread_mutex_t *mp,const pthread_mutexattr_t *mattr)
参数说明:mp 互斥锁地址, mattr 属性 通常默认null
初始化互斥锁之前,必须将其所在的内存清零。
如果互斥锁已初始化,则它会处于未锁定状态。互斥锁可以位于进程之间共享的内存中或者某个进程的专用内存中。
锁定互斥锁

函数原型:
int pthread_mutex_lock(pthread_mutex_t *mutex); #include pthread_mutex_t mutex; int ret; ret = pthread_ mutex_lock(&mp); /* acquire the mutex */

函数说明:
当 pthread_mutex_lock() 返回时,该互斥锁已被锁定。调用线程是该互斥锁的属主。如果该互斥锁已被另一个线程锁定和拥有,则调用线程将阻塞,直到该互斥锁变为可用为止。

如果互斥锁类型为 PTHREAD_MUTEX_NORMAL,则不提供死锁检测。尝试重新锁定互斥锁会导致死锁。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或未锁定,则将产生不确定的行为。

如果互斥锁类型为 PTHREAD_MUTEX_ERRORCHECK,则会提供错误检查。如果某个线程尝试重新锁定的互斥锁已经由该线程锁定,则将返回错误。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。

如果互斥锁类型为 PTHREAD_MUTEX_RECURSIVE,则该互斥锁会保留锁定计数这一概念。线程首次成功获取互斥锁时,锁定计数会设置为 1。线程每重新锁定该互斥锁一次,锁定计数就增加 1。线程每解除锁定该互斥锁一次,锁定计数就减小 1。 锁定计数达到 0 时,该互斥锁即可供其他线程获取。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。

如果互斥锁类型是 PTHREAD_MUTEX_DEFAULT,则尝试以递归方式锁定该互斥锁将产生不确定的行为。对于不是由调用线程锁定的互斥锁,如果尝试解除对它的锁定,则会产生不确定的行为。如果尝试解除锁定尚未锁定的互斥锁,则会产生不确定的行为。

返回值:
pthread_mutex_lock() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EAGAIN:由于已超出了互斥锁递归锁定的最大次数,因此无法获取该互斥锁。
EDEADLK:当前线程已经拥有互斥锁。

解除锁定互斥锁

函数原型:
int pthread_mutex_unlock(pthread_mutex_t *mutex); #include pthread_mutex_t mutex; int ret; ret = pthread_mutex_unlock(&mutex); /* release the mutex */

函数说明:pthread_mutex_unlock() 可释放 mutex 引用的互斥锁对象。互斥锁的释放方式取决于互斥锁的类型属性。如果调用 pthread_mutex_unlock() 时有多个线程被 mutex 对象阻塞,则互斥锁变为可用时调度策略可确定获取该互斥锁的线程。对于 PTHREAD_MUTEX_RECURSIVE 类型的互斥锁,当计数达到零并且调用线程不再对该互斥锁进行任何锁定时,该互斥锁将变为可用。

返回值:pthread_mutex_unlock() 在成功完成之后会返回零。
其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

EPERM :当前线程不拥有互斥锁。
使用非阻塞互斥锁锁定

函数原型:
int pthread_mutex_trylock(pthread_mutex_t *mutex); #include pthread_mutex_t mutex; int ret; ret = pthread_mutex_trylock(&mutex); /* try to lock the mutex */

函数说明:pthread_mutex_trylock() 是 pthread_mutex_lock() 的非阻塞版本。如果 mutex 所引用的互斥对象当前被任何线程(包括当前线程)锁定,则将立即返回该调用。否则,该互斥锁将处于锁定状态,调用线程是其属主。

返回值:pthread_mutex_trylock() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EBUSY :
由于 mutex 所指向的互斥锁已锁定,因此无法获取该互斥锁。

EAGAIN:描述:
由于已超出了 mutex 的递归锁定最大次数,因此无法获取该互斥锁

销毁互斥锁
函数原型:
int pthread_mutex_destroy(pthread_mutex_t *mp); #include pthread_mutex_t mp; int ret; ret = pthread_mutex_destroy(&mp); /* mutex is destroyed */请注意,没有释放用来存储互斥锁的空间。

返回值:
pthread_mutex_destroy() 在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。
EINVAL: mp 指定的值不会引用已初始化的互斥锁对象。

===线程与进程===
进程是 资源管理 的最小单位
线程是 程序执行 的最小单位

一个进程也叫主线程,线程没有父子关系,只有主副之分


===线程同步和互斥===
sleep()函数在有信号的函数中或正规编码中不能使用,会被中断,跳过执行

条件变量pthread_cond_wait()
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:
1.线程等待“条件变量的条件成立”而挂起
2.线程使“条件成立”

创建有两种方式,静态和动态
静态:pthread_cond_t cond=PTHREAD_COND_INITIALIZER
动态: pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)

尽管POSIX标准中为条件变量定义了属性,但在LinuxThreads中没有实现,因此cond_attr值通常为NULL,且被忽略

注销一个条件变量,只有在没有线程在该条件变量上等待的时候才能注销。
int pthread_cond_destroy(pthread_cond_t *cond)

等待和激发
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)

下面是使用函数pthread_cond_wait()和函数pthread_cond_signal()的一个简单的例子:

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count;

decrement_count () {

pthread_mutex_lock (&count_lock);

while(count==0)

pthread_cond_wait( &count_nonzero, &count_lock);

count=count -1;

pthread_mutex_unlock (&count_lock);

}

increment_count(){

pthread_mutex_lock(&count_lock);

if(count==0)

pthread_cond_signal(&count_nonzero);

count=count+1;

pthread_mutex_unlock(&count_lock);

}


你可能感兴趣的:(学习)