jjzjj

C++实现经典同步问题(生产者消费者、读者写者、哲学家进餐、吸烟者问题)

一棵快乐的二叉树 2024-02-27 原文

一、生产者 - 消费者问题

  • 环境:windows

问题描述:
一组生产者进程和一组消费者进程共享一个初始为空、大小为〃的缓冲区,只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或一个消费者从中取出消息。


代码:

#include <Windows.h>

#include <iostream>
#include <stdlib.h>

typedef HANDLE Semaphore;
#define P(S) WaitForSingleObject(S, INFINITE)
#define V(S) ReleaseSemaphore(S, 1, NULL)

int produceId = 1000;	//生产的的产品ID
int consumeId;			//消费的产品ID
int buf[10];			//用于存放缓存中的数据
int BUFSIZE = 10;	//缓存大小
int in = 0;				//用于表示生产者放入缓存的下表索引
int out = 0;			//用于表示消费者从缓存中那组的数据的下标索引

//初始化empty互斥量,初值为10,表示空的缓存数
Semaphore empty = CreateSemaphore(
	NULL,
	10,
	10,
	NULL
);

//初始化互斥量,用户互斥访问临界资源
Semaphore mutex = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

//初始化full互斥量,初值为0,用于表示缓存中放了多少份数据
Semaphore full = CreateSemaphore(
	NULL,
	0,
	10,
	NULL
);

DWORD WINAPI Producer(LPVOID);	//生产者线程函数
DWORD WINAPI Consumer(LPVOID);	//消费者线程函数

VOID Produce();			//生产者生产数据 的函数
VOID Consume();			//消费者消费数据的函数 

VOID printbuf();		//用于打印缓存中的数据的函数


int main()
{
    
	HANDLE produce;
	HANDLE consumer1, consumer2, consumer3;

	produce = CreateThread(
		NULL,
		0,
		Producer,
		NULL,
		0,
		NULL
	);
	consumer1 = CreateThread(
		NULL,
		0,
		Consumer,
		NULL,
		0,
		NULL
	);
	consumer2 = CreateThread(
		NULL,
		0,
		Consumer,
		NULL,
		0,
		NULL
	);
	consumer3 = CreateThread(
		NULL,
		0,
		Consumer,
		NULL,
		0,
		NULL
	);
	while (1)
	{
		WaitForSingleObject(produce, INFINITE);
		WaitForSingleObject(consumer1, INFINITE);
		WaitForSingleObject(consumer2, INFINITE);
		WaitForSingleObject(consumer3, INFINITE);
	}

	return 0;
}

VOID printbuf() {
	std::cout << "缓存中的数据:";
	bool hasData = false;
	for (int i = 0; i < BUFSIZE; i++) {
		if (buf[i] != 0) {
			std::cout << buf[i] << "----";
			hasData = true;
		}
	}
	if (hasData)
		std::cout << std::endl;
	else
		std::cout << "无" << std::endl;
}

VOID Produce() {
	produceId++;
	buf[in++] = produceId;
	std::cout << "我是生产者,我生产了:" << produceId << std::endl;
	printbuf();
	in %= BUFSIZE;
}

VOID Consume() {
	consumeId = buf[out];
	std::cout << "我是消费者,我消费了:" << consumeId << std::endl;
	buf[out++] = 0;
	printbuf();
	out %= BUFSIZE;
}

DWORD WINAPI Producer(LPVOID) {
	while (1) {
		P(empty);		//有无空缓存
		P(mutex);		//互斥夹紧临界资源
		Produce();		//生产数据
		Sleep(1000);
		V(mutex);		//互斥夹紧临界资源
		V(full);		//full值+1
	}
	return 0;
}

DWORD WINAPI Consumer(LPVOID) {
	while (1) {
		P(full);		//缓存中有无数据
		P(mutex);		//互斥夹紧临界资源
		Consume();		//消费数据
		Sleep(1000);
		V(mutex);		//互斥夹紧临界资源
		V(empty);		//空缓存数加1
	}
	return 0;
}

运行效果:

再来看一个复杂一点的生产者 - 消费者问题:
桌子上有一个盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果。只有盘子为空时, 爸爸或妈妈才可向盘子中放一个水果;仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取岀。


代码:

#include <Windows.h>

#include <iostream>
#include <stdlib.h>

typedef HANDLE Semaphore;
#define P(S) WaitForSingleObject(S, INFINITE)
#define V(S) ReleaseSemaphore(S, 1, NULL)

#define _NULL 0
#define _APPLE 1
#define _ORANGE 2
#define _FATHER 1
#define _MOTHER 2
#define _SON 3
#define _DAUGHTER 4

int what = 0;			//用于表示是哪种水果
int who = 0;			//用于表示是哪位放了或者吃了水果

//初始化apple互斥量,初值为0,用于表示盘中是否放了苹果
Semaphore apple = CreateSemaphore(
	NULL,
	0,
	1,
	NULL
);

//初始化orange互斥量,初值为0,用于表示盘中是否放了橘子
Semaphore orange = CreateSemaphore(
	NULL,
	0,
	1,
	NULL
);

//初始化plate互斥量,用于表示盘中是否有水果
Semaphore plate = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

DWORD WINAPI Father(LPVOID);	//父亲线程函数
DWORD WINAPI Mother(LPVOID);	//母亲线程函数
DWORD WINAPI Son(LPVOID);		//儿子线程函数
DWORD WINAPI Daughter(LPVOID);	//女儿线程函数

VOID Put(int);			//父母放水果的函数
VOID Get();				//儿女吃水果的函数 

VOID PrintPlate();		//用于打印的函数


int main()
{

	HANDLE father, mother, son, daughter;;

	father = CreateThread(
		NULL,
		0,
		Father,
		NULL,
		0,
		NULL
	);
	mother = CreateThread(
		NULL,
		0,
		Mother,
		NULL,
		0,
		NULL
	);
	son = CreateThread(
		NULL,
		0,
		Son,
		NULL,
		0,
		NULL
	);
	daughter = CreateThread(
		NULL,
		0,
		Daughter,
		NULL,
		0,
		NULL
	);
	while (1)
	{
		WaitForSingleObject(father, INFINITE);
		WaitForSingleObject(mother, INFINITE);
		WaitForSingleObject(son, INFINITE);
		WaitForSingleObject(daughter, INFINITE);
	}

	return 0;
}

VOID PrintPlate() {
	std::string _who[4] = {
		"爸爸",
		"妈妈",
		"儿子",
		"女儿"
	};
	std::string _what[2] = {
		"苹果",
		"橘子"
	};
	if (who == _FATHER || who == _MOTHER) {
		std::cout << "我是:" << _who[who - 1].c_str()
			<< ";  我放了【" << _what[what - 1].c_str() << "】在盘子里...."
			<< std::endl;
	}
	else {
		std::cout << "我是:" << _who[who - 1].c_str()
			<< ";  我从盘子里把【" << _what[what - 1].c_str() << "】拿走了...."
			<< std::endl;
	}
}

VOID Put(int id) {
	what = (id == _APPLE) ? _APPLE : _ORANGE;
	who = (id == _FATHER) ? _FATHER : _MOTHER;
	PrintPlate();
}

VOID Get() {
	who = (what == _APPLE) ? _DAUGHTER : _SON;
	PrintPlate();
	what = _NULL;
}

DWORD WINAPI Father(LPVOID) {
	while (1) {
		P(plate);				//看盘子是否为空
		Put(_APPLE);			//父亲放入苹果
		Sleep(1000);
		V(apple);				//唤醒女儿线程
	}
	return 0;
}

DWORD WINAPI Mother(LPVOID) {
	while (1) {
		P(plate);				//看盘子是否为空
		Put(_ORANGE);			//母亲放入橘子
		Sleep(1000);
		V(orange);				//唤醒儿子线程
	}
	return 0;
}

DWORD WINAPI Son(LPVOID) {
	while (1) {
		P(orange);				//看盘子里是否有橘子
		Get();					//拿走橘子
		Sleep(1000);
		V(plate);				//盘子变空,唤醒父母
	}
	return 0;
}

DWORD WINAPI Daughter(LPVOID) {
	while (1) {
		P(apple);				//看盘子里是否有苹果
		Get();					//拿走苹果
		Sleep(1000);
		V(plate);				//盘子变空,唤醒父母
	}
	return 0;
}

运行效果:

二、读者 - 写者问题

问题描述:
有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者往文件中写信息;③任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。


读优先(读优先可能会导致写者线程饿死)的代码:

//读者优先,读者优先可能导致写进程饿死
#include <Windows.h>

#include <iostream>
#include <stdlib.h>

typedef HANDLE Semaphore;
#define P(S) WaitForSingleObject(S, INFINITE)
#define V(S) ReleaseSemaphore(S, 1, NULL)

int count = 0;			//用于记录读者数量

//初始化mutex互斥量,用于保证互斥访问count
Semaphore mutex = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

//初始化rw互斥量,用于保证读写进程 互斥地访问文件
Semaphore rw = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

DWORD WINAPI Reader(LPVOID);	//读者线程函数
DWORD WINAPI Writer(LPVOID);	//写者线程函数

VOID Read();				//读函数
VOID Write();				//写函数


int main()
{

	HANDLE reader[5];
	HANDLE writer[5];

	for (int i = 0; i < 5; i++) {
		reader[i] = CreateThread(
			NULL,
			0,
			Reader,
			NULL,
			0,
			NULL
		);
	}

	for (int i = 0; i < 5; i++) {
		writer[i] = CreateThread(
			NULL,
			0,
			Writer,
			NULL,
			0,
			NULL
		);
	}

	while (1)
	{
		for (int i = 0; i < 20; i++)
			WaitForSingleObject(reader[i], INFINITE);
		
		for (int i = 0; i < 5; i++)
			WaitForSingleObject(writer[i], INFINITE);
	}

	return 0;
}

VOID Read() {
	std::cout << "我是读线程,我正在读......." << std::endl;
}

VOID Write() {
	std::cout << "我是写线程,我正在写---------------" << std::endl;
}

DWORD WINAPI Reader(LPVOID) {
	while (1) {
		P(mutex);			//互斥访问count变量
		if (count == 0)		//当第一个读线程读共享文件时
			P(rw);			//阻塞写线程
		count++;			//读线程数加 1
		Sleep(1000);
		V(mutex);			//互斥访问count变量
		Read();				//读取共享文件
		P(mutex);			//互斥访问count变量
		count--;			//读线程数减 1
		if (count == 0)		//当当前没有读线程工作时
			V(rw);			//释放rw信号量,通知写线程可以工作了
		V(mutex);			//互斥访问count变量
	}
	return 0;
}

DWORD WINAPI Writer(LPVOID) {
	while (1) {
		P(rw);				//保证互斥访问共享文件
		Write();			//写共享文件
		Sleep(300);
		V(rw);				//保证互斥访问共享文件
	}
	return 0;
}

运行效果:

注:可以看到,由于读者线程优先,导致了写者线程饿死

写优先,或者叫读写平衡的代码:

//写者优先,或者叫读写平衡
#include <Windows.h>

#include <iostream>
#include <stdlib.h>

typedef HANDLE Semaphore;
#define P(S) WaitForSingleObject(S, INFINITE)
#define V(S) ReleaseSemaphore(S, 1, NULL)

int count = 0;			//用于记录读者数量

//初始化mutex互斥量,用于保证互斥访问count
Semaphore mutex = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

//初始化rw互斥量,用于保证读写进程 互斥地访问文件
Semaphore rw = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

//初始化w互斥量,用于实现“写优先”
Semaphore w = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

DWORD WINAPI Reader(LPVOID);	//读者线程函数
DWORD WINAPI Writer(LPVOID);	//写者线程函数

VOID Read();				//读函数
VOID Write();				//写函数


int main()
{

	HANDLE reader[5];
	HANDLE writer[5];

	for (int i = 0; i < 5; i++) {
		reader[i] = CreateThread(
			NULL,
			0,
			Reader,
			NULL,
			0,
			NULL
		);
	}

	for (int i = 0; i < 5; i++) {
		writer[i] = CreateThread(
			NULL,
			0,
			Writer,
			NULL,
			0,
			NULL
		);
	}

	while (1)
	{
		for (int i = 0; i < 20; i++)
			WaitForSingleObject(reader[i], INFINITE);

		for (int i = 0; i < 5; i++)
			WaitForSingleObject(writer[i], INFINITE);
	}

	return 0;
}

VOID Read() {
	std::cout << "我是读线程,我正在读......." << std::endl;
}

VOID Write() {
	std::cout << "我是写线程,我正在写---------------" << std::endl;
}

DWORD WINAPI Reader(LPVOID) {
	while (1) {
		P(w);				//保证在无写线程时进入
		P(mutex);			//互斥访问count变量
		if (count == 0)		//当第一个读线程读共享文件时
			P(rw);			//阻塞写线程
		count++;			//读线程数加 1
		Sleep(1000);
		V(mutex);			//互斥访问count变量
		V(w);				//释放w,保证写线程优先
		Read();				//读取共享文件
		P(mutex);			//互斥访问count变量
		count--;			//读线程数减 1
		if (count == 0)		//当当前没有读线程工作时
			V(rw);			//释放rw信号量,通知写线程可以工作了
		V(mutex);			//互斥访问count变量
	}
	return 0;
}

DWORD WINAPI Writer(LPVOID) {
	while (1) {
		P(w);				//在无写线程时进入
		P(rw);				//保证互斥访问共享文件
		Write();			//写共享文件
		Sleep(300);
		V(rw);				//保证互斥访问共享文件
		V(w);				//写完毕,释放
	}
	return 0;
}

运行效果:

注:可以看到写者线程被调度了

三、哲学家进餐问题

问题描述:
一张圆桌边上坐着5名哲学家,每两名哲学家之间的桌上摆一根筷子,两根筷子中间是一碗米饭,如图2.12所示。哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。若筷子已在他人手上,则需要等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,进餐完毕后,放下筷子继续思考。

代码:

#include <Windows.h>

#include <iostream>
#include <stdlib.h>

typedef HANDLE Semaphore;
#define P(S) WaitForSingleObject(S, INFINITE)
#define V(S) ReleaseSemaphore(S, 1, NULL)

//筷子互斥量,初值为1,表示是否有筷子
Semaphore chopstick[5];

//初始化mutex互斥量,用于保证互斥访问chopstick
Semaphore mutex = CreateSemaphore(
	NULL,
	1,
	1,
	NULL
);

DWORD WINAPI Philosopher(LPVOID);	//哲学家线程函数

VOID InitSemaphore();

VOID Eat(int);							//哲学家进餐函数
VOID Think(int);						//哲学家思考函数

int main()
{
	InitSemaphore();

	HANDLE philosopher[5];
	int id[5];
	for (int i = 0; i < 5; i++)
		id[i] = i;

	for (int i = 0; i < 5; i++) {
		philosopher[i] = CreateThread(
			NULL,
			0,
			Philosopher,
			(LPVOID)&(id[i]),
			0,
			NULL
		);
	}

	while (1)
	{
		for (int i = 0; i < 5; i++)
			WaitForSingleObject(philosopher[i], INFINITE);
	}

	return 0;
}

VOID InitSemaphore() {
	for (int i = 0; i < 5; i++) {
		chopstick[i] = CreateSemaphore(
			NULL,
			1,
			1,
			NULL
		);
	}
}

VOID Eat(int i) {
	std::cout << "哲学家【" << i + 1 << "】正在进餐..." << std::endl;
}

VOID Think(int i) {
	std::cout << "哲学家【" << i + 1 << "】正在思考........" << std::endl;
}

DWORD WINAPI Philosopher(LPVOID i) {
	while (1) {
		P(mutex);								//互斥访问筷子
		P(chopstick[*((int *)i)]);				//拿起左手边的筷子
		P(chopstick[((*((int *)i)) + 1) % 5]);	//拿起右手边的筷子
		V(mutex);								//互斥访问筷子
		Eat(*(int *)i);							//进餐
		Sleep(1000);
		V(chopstick[*((int *)i)]);				//放下左手边的筷子
		V(chopstick[((*((int *)i) + 1)) % 5]);	//放下右手边的筷子
		Think(*(int *)i);						//思考.....在这里可能发生竟态条件
	}
	return 0;
}

运行效果:

注:以上思考的输出出现混乱的原因:

在一个哲学家线程调用到 Think 函数的时候由于没有信号量的保护,因此可能发生竟态条件,由于线程异步地执行,可能在某个线程运行 Think 的时候发生了调度。

四、吸烟者问题

问题描述:
假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草,第二个拥有纸,第三个拥有胶水。供应者进程无限地提供三种材料,供应者每次将两种材料放到桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者一个信号告诉已完成,此时供应者就会将另外两种材料放到桌上,如此重复(让三个抽烟者轮流地抽烟)。

代码:

#include <Windows.h>

#include <iostream>
#include <stdlib.h>

typedef HANDLE Semaphore;
#define P(S) WaitForSingleObject(S, INFINITE)
#define V(S) ReleaseSemaphore(S, 1, NULL)

#define YanCaoAndZhi 1
#define YanCaoAndJiaoShui 2
#define ZhiAndJiaoShui 3

int num;			//供应者供应用的 随机数
int what;			//表示桌上有什么材料

//初始化offerYanCao互斥量,用于表示供应烟草和纸
Semaphore offerYanCaoAndZhi = CreateSemaphore(
	NULL,
	0,
	1,
	NULL
);

//初始化offerZhi互斥量,用于表示供应烟草和胶水
Semaphore offerYanCaoAndJiaoShui = CreateSemaphore(
	NULL,
	0,
	1,
	NULL
);

//初始化offerJiaoShui互斥量,用于表示供应纸和胶水
Semaphore offerZhiAndJiaoShui = CreateSemaphore(
	NULL,
	0,
	1,
	NULL
);

//初始化finish互斥量,用于表示吸烟完成
Semaphore finish = CreateSemaphore(
	NULL,
	0,
	1,
	NULL
);

DWORD WINAPI Producer(LPVOID);	//供应者线程函数
DWORD WINAPI Smoker1(LPVOID);	//1号吸烟者,拥有烟草
DWORD WINAPI Smoker2(LPVOID);	//2号吸烟者,拥有纸
DWORD WINAPI Smoker3(LPVOID);	//3号吸烟者,拥有胶水

VOID Put(int);					//供应者放材料
VOID Smoke();				//吸烟者吸烟


int main()
{

	HANDLE producer;
	HANDLE smoker1, smoker2, smoker3;

	
	producer = CreateThread(
		NULL,
		0,
		Producer,
		NULL,
		0,
		NULL
	);

	smoker1 = CreateThread(
		NULL,
		0,
		Smoker1,
		NULL,
		0,
		NULL
	);

	smoker2 = CreateThread(
		NULL,
		0,
		Smoker2,
		NULL,
		0,
		NULL
	);

	smoker3 = CreateThread(
		NULL,
		0,
		Smoker3,
		NULL,
		0,
		NULL
	);

	while (1)
	{
		WaitForSingleObject(producer, INFINITE);
		WaitForSingleObject(smoker1, INFINITE);
		WaitForSingleObject(smoker2, INFINITE);
		WaitForSingleObject(smoker3, INFINITE);
	}

	return 0;
}

VOID Put(int i) {
	if (i == YanCaoAndZhi) {
		what = YanCaoAndZhi;
		std::cout << "我是供应者,我现在要把【烟草】和【纸】放到桌上" << std::endl;
	}
	else if (i == YanCaoAndJiaoShui) {
		what = YanCaoAndJiaoShui;
		std::cout << "我是供应者,我现在要把【烟草】和【胶水】放到桌上" << std::endl;
	}
	else {
		what = ZhiAndJiaoShui;
		std::cout << "我是供应者,我现在要把【纸】和【胶水】放到桌上" << std::endl;
	}
}

VOID Smoke() {
	if (what == YanCaoAndZhi) {
		std::cout << "我是吸烟者【3】号,我拥有【胶水】,我现在从桌上拿走【烟草】和【纸】,我开始吸烟了"
			<< std::endl;
	}	
	else if (what == YanCaoAndJiaoShui) {
		std::cout << "我是吸烟者【2】号,我拥有【纸】,我现在从桌上拿走【烟草】和【胶水】,我开始吸烟了"
			<< std::endl;
	}
	else {
		std::cout << "我是吸烟者【1】号,我拥有【烟草】,我现在从桌上拿走【纸】和【胶水】,我开始吸烟了"
			<< std::endl;
	}
	what = 0;
}

DWORD WINAPI Producer(LPVOID) {
	while (1) {
		num++;							//要放入什么
		num = num % 3;					
		if (num == 0) {
			Put(YanCaoAndZhi);			//放入烟草和纸
			V(offerYanCaoAndZhi);		//唤醒拥有胶水的吸烟者
		}
		else if (num == 1) {
			Put(YanCaoAndJiaoShui);		//放入烟草和胶水
			V(offerYanCaoAndJiaoShui);	//唤醒拥有纸的吸烟者
			
		}
		else {
			Put(ZhiAndJiaoShui);		//放入纸和胶水
			V(offerZhiAndJiaoShui);		//唤醒拥有烟草的吸烟者
		}
		Sleep(1000);
		P(finish);						//是否有吸烟者吸完烟了?
	}
	return 0;
}

DWORD WINAPI Smoker1(LPVOID){			//拥有烟草的吸烟者
	while (1) {
		P(offerZhiAndJiaoShui);			//供应者是否放好了纸和胶水
		Smoke();						//拿走材料开始吸烟
		Sleep(1000);
		V(finish);
	}
	return 0;
}

DWORD WINAPI Smoker2(LPVOID) {			//拥有纸的吸烟者
	while (1) {
		P(offerYanCaoAndJiaoShui);		//供应者是否放好了烟草和胶水
		Smoke();						//拿走材料开始吸烟
		Sleep(1000);
		V(finish);
	}
	return 0;
}

DWORD WINAPI Smoker3(LPVOID) {			//拥有胶水的吸烟者
	while (1) {
		P(offerYanCaoAndZhi);			//供应者是否放好了烟草和纸
		Smoke();						//拿走 材料开始吸烟
		Sleep(1000);
		V(finish);
	}
	return 0;
}

运行效果:

有关C++实现经典同步问题(生产者消费者、读者写者、哲学家进餐、吸烟者问题)的更多相关文章

  1. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  4. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  7. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  8. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  9. 【高数】用拉格朗日中值定理解决极限问题 - 2

    首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有,  也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加

  10. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

随机推荐