一.条件变量
1. include<pthread.h>
pthread_cond_init(pthread_cond_t* cond (条件变量的地址) ,const pthread _condattr_t* cond_attr(属性传NULL即可))--->初始化
pthread_cond_destroy(pthread_cond_t * cond(条件变量))-->销毁
pthread_cond_broadcast(pthread_cond_t * cond(条件变量))-->唤醒,通知线程工作(将所有在条件变量等待队列的线程全部唤醒)
pthread_cond_signal(pthread_cond_t * cond(条件变量))-->唤醒,通知线程工作(只唤醒一个线程工作)
pthread_cond_wait(pthread_cond_t * cond(条件变量), pthread_mutex_t * mutex(互斥锁))-->将当前线程放到条件变量等待队列上,然后阻塞住。

2.测试条件变量:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
pthread_cond_t cond;
pthread_mutex_t mutex;
char buff[128] = {0};
//打印主线程输入的字符串
void* fun1(void* arg)
{
while( 1 )
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);//阻塞-->调用后函数内部会先进行解锁操作,当成功返回后会进行加锁操作,故在使用前要先进行加锁,使用后要进行解锁
pthread_mutex_unlock(&mutex);
if( strncmp(buff,"end",3) == 0 )
{
break;
}
printf("fun1 buff=%s\n",buff);//两个线程都进行打印
}
}
//打印主线程输入的字符串
void* fun2(void* arg)
{
while( 1 )
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);//阻塞
pthread_mutex_unlock(&mutex);
if( strncmp(buff,"end",3) == 0 )
{
break;
}
printf("fun2 buff=%s\n",buff);
}
}
int main()
{
pthread_cond_init(&cond,NULL);//条件变量
pthread_mutex_init(&mutex,NULL);//互斥锁
pthread_t id1,id2;
pthread_create(&id1,NULL,fun1,NULL);
pthread_create(&id2,NULL,fun2,NULL);
while(1)
{
fgets(buff,128,stdin);
if ( strncmp(buff,"end",3) == 0 )
{
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond);//唤醒全部线程
pthread_mutex_unlock(&mutex);
break;//退出前要将被阻塞的线程唤醒
}
else
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);//随机唤醒1个线程
pthread_mutex_unlock(&mutex);
}
}
pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_cond_destroy(&cond);
pthread_metux_destroy(&mutex);
exit(0);
}
3.多线程程序fork后,子进程只有一条执行路径,就是fork所在的执行路径。测试代码如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void*fun(void*arg)
{
fork();//fork在子线程中,子程序只执行子线程的路径
for(int i=0;i<5;i++)
{
printf("fun pid=%d\n",getpid());
sleep(1);
}
}
int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
//fork();//fork在主线程中,子程序只执行主线程的路径
for(int i=0;i<5;i++)
{
printf("main pid=%d\n",getpid());
sleep(1);
}
}
4.linux线程是以进程的方式实现的,所有线程是共享同一个进程的资源,但进程结束后,线程也就消失了。与fork不同,fork有多个进程,一个进程结束了,不影响其他的进程。
在linux系统中,线程就是当fork()后产生的子进程与父进程共享内存,地址空间等资源,而且产生的所有子进程都是共享父进程的资源,看起来就是一个进程里面的线程。

5.线程总结(常考):
(1)进程与线程的区别:线程进程内部的一条执行路径(序列),一个进程可以包含多个线程 进程是一个正在运行的程序。
(2)并发与并行的区别:并发运行是交替进行(1个处理器) 并行是同时进行(2个以上处理器)
(3)线程同步(通信)的方法:信号量,互斥锁,读写锁,条件变量
(4)线程安全(会结合项目):多线程程序无论调度的顺序如何,都能得到正确的结果
(5)给场景进行PV操作:如生产者消费者
二.网络的基础概念
1.网络:就是把不同的计算机连接起来构成了网络。 连接起来需要网络设备(路由器,交换机)和传输介质(网线,光纤等等) 。 联网的目的就是信息交互与资源共享。
2.互联网:将不同的网络连接起来就是互联网。
3.ip地址(在整个网络中唯一标识一台主机,要动态去分配): ipv4(32位-->2^32) ipv6(128位-->2^128)
MAC地址(每台电脑唯一标识,是固定的,48位的数字):物理地址
MAC可以唯一标识一台主机为什么还要IP地址:MAC物理地址是一个平面的没有结构的,无法反映出物理位置发生了变化,要传信息就必须要有物理地址,一但发生了变化就接收不到信息。但IP地址是随着位置的改变而发生改变的,从而可以一直找到该地址,就可以进行信息的传输。
4.IP地址的表示形式:32位每8位是一个字节,共4个字节。 范围:0~255 点分十进制的IP地址:如127.0.0.1等等。
5.在window中查看IP信息:ipconfig
在Linux中查看IP信息:ifconfig
6.127.0.0.1:测试用的IP地址,当计算机没有联网时,测试网卡能不能发送,能不能接收,就是自己给自己发,不用经过网络,它会把发送缓冲区的数据直接导到接收缓冲区。
7.端口-->port: 软件层面 short类型,是应用程序的代号(如微信,浏览器等等) 一个IP+一个port可以唯一标识一台主机的一个进程。 通信时要有两对IP和端口。

8.网络协议:网络规则的集合(如tcp协议,udp协议,ip协议)
9.网络分层:OSI模型的七层模型 tcp/ip的四层模型--->传输层的重要协议:
tcp协议(像打电话)--->tcp特点:面向连接的 可靠的 流式服务。
udp协议(像发短信)-->udp特点:无连接的 不可靠的 数据报服务

为什么要分层:

10.主机之间怎么进行信息的传输:根据四层协议来描述,其中tcp表示tcp报头(头部的大小是固定的),IP表示ip报头,在数据链路层会形成数据帧,分为帧头与帧尾。
从上而下依次是应用层,传输层,网络层,数据链路层

655

被折叠的 条评论
为什么被折叠?



