C++和JAVA的编译模式
2013-04-24 08:17
246 查看
c/c++_xiaoxiao(1) 0:53:45
C:\Users\tiny>cat 1.cpp
class Base {
public:
static int a;
};
int Base::a = 1;
template <typename T>
class C {
public:
static void demo() {
T::a = 100;
}
};
int main()
{
C<Base>::demo();
return 0;
}
C:\Users\tiny>g++ 1.cpp
C:\Users\tiny>
c/c++_xiaoxiao(1) 0:53:49
没辙,这就是区别。。
Linux_C_Jecon<2> 0:54:04
不行。。。
Linux_C_Jecon<2> 0:54:08
NND 语法规定
Linux_C_Jecon<2> 0:54:28
c++不严谨哎
c/c++_xiaoxiao(1) 0:54:28
所以我说,写多了c++,容易为所欲为。。
c/c++_xiaoxiao(1) 0:54:35
很严谨啊
c/c++_xiaoxiao(1) 0:54:48
T确实有一个静态成员是a啊
c/c++_xiaoxiao(1) 0:54:54
既然有,那就可以访问啊
Linux_C_Jecon<2> 0:55:15
问题是java的入口类是静态的啊
c/c++_xiaoxiao(1) 0:55:26
这和静态动态无关啊
Linux_C_Jecon<2> 0:55:30
有啊
Linux_C_Jecon<2> 0:55:34
我发给你看嘛
c/c++_xiaoxiao(1) 0:55:41
主要是,java的泛型是运行时的
c/c++_xiaoxiao(1) 0:55:43
这个才是悲剧
Linux_C_Jecon<2> 0:56:02
class DBM<Type extends Base>{
public void demo(){
Type.a=100;
System.out.println("Type.a="+Type.a);
}
}
Linux_C_Jecon<2> 0:56:06
这个是动态的
Linux_C_Jecon<2> 0:56:22
Linux_C_Jecon<2> 0:56:27
改成静态的就报错
Linux_C_Jecon<2> 0:56:42
跟泛型无关啊
Linux_C_Jecon<2> 0:56:49
跟语法有关吧
c/c++_xiaoxiao(1) 0:56:53
核心在于,泛型本身是运行时确定的
c/c++_xiaoxiao(1) 0:57:00
static是静态的
Linux_C_Jecon<2> 0:57:08
是啊
c/c++_xiaoxiao(1) 0:57:10
没法获知泛型本身的类型了。
c/c++_xiaoxiao(1) 0:57:19
所以说...java弱啊。。。
Linux_C_Jecon<2> 0:57:20
Linux_C_Jecon<2> 0:57:25
看嘛 没办法嘛
c/c++_xiaoxiao(1) 0:57:25
泛型如果是编译时的话
c/c++_xiaoxiao(1) 0:57:27
就没这个问题了。
Linux_C_Jecon<2> 0:57:33
跟Type无关啊
Linux_C_Jecon<2> 0:57:43
不是编译时的问题
c/c++_xiaoxiao(1) 0:57:44
所以,要学c++啊,把泛型丢到编译时,一点问题都没了。
Linux_C_Jecon<2> 0:58:06
这个是直接写成你那样的。eclipse语法解析器就报错了
Linux_C_Jecon<2> 0:58:10
还没进入编译
c/c++_xiaoxiao(1) 0:58:24
...之所以不支持这个语法
Linux_C_Jecon<2> 0:58:27
这个是未编译的状态啊
Linux_C_Jecon<2> 0:58:28
恩恩
Linux_C_Jecon<2> 0:58:32
不支持这个语法
c/c++_xiaoxiao(1) 0:58:32
就是因为,泛型是运行时确定的啊
c/c++_xiaoxiao(1) 0:58:43
你想想啊
Linux_C_Jecon<2> 0:58:49
跟泛型无关啊啊
Linux_C_Jecon<2> 0:58:56
换别的写法也不行啊
c/c++_xiaoxiao(1) 0:59:00
因为,static是要在所有runtime加载前执行的
c/c++_xiaoxiao(1) 0:59:22
算了,我改天看看java的类加载器去,就明白了
c/c++_xiaoxiao(1) 0:59:25
为什么这个语法不让通过。
c/c++_xiaoxiao(1) 0:59:31
现在貌似很难解释。
Linux_C_Jecon<2> 1:00:29
Linux_C_Jecon<2> 1:00:39
不难解释啊
c/c++_xiaoxiao(1) 1:00:46
简单的说,static的时候,没有new出一个DBM的对象,那么他就不知道泛型是啥。
Linux_C_Jecon<2> 1:00:51
是
c/c++_xiaoxiao(1) 1:00:54
那么,他就无法判断出,这个泛型到底有啥成员
c/c++_xiaoxiao(1) 1:01:08
说白了,根本还在于,泛型必须运行时才能知道
c/c++_xiaoxiao(1) 1:01:18
c++之所以允许,是因为,泛型是处理是在编译时
Linux_C_Jecon<2> 1:01:22
简单的说,static的时候,没有new出一个DBM的对象,那么他就不让他传值
Linux_C_Jecon<2> 1:01:35
。。。。这个语法上明显不行嘛
c/c++_xiaoxiao(1) 1:01:39
因为,java的泛型是metadata
Linux_C_Jecon<2> 1:01:44
跟泛型没关系吧
c/c++_xiaoxiao(1) 1:01:50
额。
c/c++_xiaoxiao(1) 1:01:56
你这样理解也没错
Linux_C_Jecon<2> 1:02:08
是啊
Linux_C_Jecon<2> 1:02:22
确实是静态方法调不了动态方法啊
c/c++_xiaoxiao(1) 1:02:25
java的泛型是metadata
c/c++_xiaoxiao(1) 1:02:27
那么
Linux_C_Jecon<2> 1:02:34
不管换什么类型都一样啊
c/c++_xiaoxiao(1) 1:02:33
只有这个对象生成以后
Linux_C_Jecon<2> 1:02:38
恩
c/c++_xiaoxiao(1) 1:02:38
metadata才会初始化
c/c++_xiaoxiao(1) 1:02:39
你听我说完
c/c++_xiaoxiao(1) 1:02:49
那么,这个时候才知道,metadata里面这个类型,到底有啥成员
c/c++_xiaoxiao(1) 1:03:00
static的话,metadata压根没有被传递进去
c/c++_xiaoxiao(1) 1:03:07
所以,无法判断出,这个类型到底是啥
c/c++_xiaoxiao(1) 1:03:14
因为,java的类型,其实就在metadata里,对吧
c/c++_xiaoxiao(1) 1:03:25
你换这个角度理解,和泛型有关了么?
Linux_C_Jecon<2> 1:03:27
恩
c/c++_xiaoxiao(1) 1:03:35
通了吧
Linux_C_Jecon<2> 1:03:47
恩
c/c++_xiaoxiao(1) 1:03:48
c++的泛型,是编译期间,对每一行代码
c/c++_xiaoxiao(1) 1:03:52
都去做类型的匹配
Linux_C_Jecon<2> 1:03:53
你看的是哪本书啊
c/c++_xiaoxiao(1) 1:04:11
所以,c++的泛型,不依赖运行时的check,在编译的时候,比如我刚才给的代码
c/c++_xiaoxiao(1) 1:04:15
c<base>::demo()
Linux_C_Jecon<2> 1:04:16
哦
c/c++_xiaoxiao(1) 1:04:20
他首先回去看demo这个函数
c/c++_xiaoxiao(1) 1:04:24
demo里面,有T::a
c/c++_xiaoxiao(1) 1:04:29
然后,C的模板参数是Base
Linux_C_Jecon<2> 1:04:32
恩
c/c++_xiaoxiao(1) 1:04:39
T被实例化成Base类型
c/c++_xiaoxiao(1) 1:04:45
那么,他会去检查,Base有没有一个静态成员a
c/c++_xiaoxiao(1) 1:04:49
如果有,pass,没有报错
c/c++_xiaoxiao(1) 1:04:56
不需要到运行时去做check
Linux_C_Jecon<2> 1:05:12
你没看出什么问题吗
c/c++_xiaoxiao(1) 1:05:18
说白了,还是因为java的泛型实例化的时机和c++不同,导致了这个语法必定不能通过
Linux_臭臭<pylay.shen@gmail.com> 1:05:39
wing 在哪设置字符集呢
Linux_C_Jecon<2> 1:05:46
恩
Linux_C_Jecon<2> 1:05:48
是的
c/c++_xiaoxiao(1) 1:06:00
这样解释都通了吧?
c/c++_xiaoxiao(1) 1:06:05
没啥疑问了吧
c/c++_xiaoxiao(1) 1:06:23
书啊,看java虚拟机的相关资料吧
c/c++_xiaoxiao(1) 1:06:40
因为java的泛型本质是metadata,所以对于内置类型
Linux_C_Jecon<2> 1:06:46
C:\Users\tiny>cat 1.cpp
class Base {
public:
static int a;
};
int Base::a = 1;
template <typename T>
class C {
public:
static void demo() {
T::a = 100;
}
};
这句话在JAVA里面是明显过不去的
Linux_C_Jecon<2> 1:06:47
恩恩
c/c++_xiaoxiao(1) 1:06:47
int short float double这种
c/c++_xiaoxiao(1) 1:06:51
就不能实例化了
Linux_C_Jecon<2> 1:07:00
你的T是动态的吧
c/c++_xiaoxiao(1) 1:07:03
所以,你无法生成一个List<int>
Linux_C_Jecon<2> 1:07:06
是
c/c++_xiaoxiao(1) 1:07:16
没错吧,本质和泛型还是有关吧
Linux_C_Jecon<2> 1:07:22
恩
c/c++_xiaoxiao(1) 1:07:22
不过你是从语言本身的语法入手
Linux_C_Jecon<2> 1:07:31
是的
c/c++_xiaoxiao(1) 1:07:30
我是从语言为什么不能这样设计入手的
Linux_C_Jecon<2> 1:07:37
哦
c/c++_xiaoxiao(1) 1:07:37
臭臭,貌似不能
c/c++_xiaoxiao(1) 1:07:52
我记得wingware不能设置非utf-8字符集
c/c++_xiaoxiao(1) 1:08:01
c++那个其实是静态的
Linux_C_Jecon<2> 1:08:07
那好吧
Linux_臭臭<pylay.shen@gmail.com> 1:08:09
不能 我也没找到
c/c++_xiaoxiao(1) 1:08:10
java把泛型做到了metadata里的好处是
c/c++_xiaoxiao(1) 1:08:13
你可以反射处理
Linux_C_Jecon<2> 1:08:14
就出在这个问题上
Linux_C_Jecon<2> 1:08:17
恩恩
Linux_C_Jecon<2> 1:08:31
用反射 直接调用类,不进行实例化就OK了
c/c++_xiaoxiao(1) 1:08:32
你可以运行时,通过反射,对一个泛型实例化
c/c++_xiaoxiao(1) 1:08:36
但是,c++就不行了
c/c++_xiaoxiao(1) 1:08:41
一样的,本质差不多
Linux_C_Jecon<2> 1:08:46
c++没有反射吧
c/c++_xiaoxiao(1) 1:08:45
反正都是通过metadata
c/c++_xiaoxiao(1) 1:08:48
对吧
Linux_C_Jecon<2> 1:08:55
是的
c/c++_xiaoxiao(1) 1:08:57
c++的泛型是编译时确定的
c/c++_xiaoxiao(1) 1:09:04
那么就是说,运行时,你永远不知道他是啥。。。
Linux_C_Jecon<2> 1:09:05
xiaoxiao有什么好书推荐几本
c/c++_xiaoxiao(1) 1:09:09
你也就无法生成2个一样的类型了。
Linux_C_Jecon<2> 1:09:11
恩
c/c++_xiaoxiao(1) 1:09:44
一个是static的,一个是runtime的,其实都有好处,只是,有时候太弱了。。。
c/c++_xiaoxiao(1) 1:09:50
好书?深入理解java虚拟机。。。
c/c++_xiaoxiao(1) 1:09:51
看么。。
Linux_C_Jecon<2> 1:09:52
是啊
Linux_C_Jecon<2> 1:10:09
额,公司刚买回来
Linux_C_Jecon<2> 1:10:13
还没去看
c/c++_xiaoxiao(1) 1:10:22
clr via c#
Linux_C_Jecon<2> 1:10:42
有没有C++线程类的书籍推荐下
c/c++_xiaoxiao(1) 1:10:48
线程?
Linux_C_Jecon<2> 1:11:01
并发类的
c/c++_xiaoxiao(1) 1:11:02
多线程本质和c++无关吧
Linux_C_Jecon<2> 1:11:12
恩
Linux_C_Jecon<2> 1:11:18
api总有吧
c/c++_xiaoxiao(1) 1:11:29
你到底是要看设计
c/c++_xiaoxiao(1) 1:11:31
还是要看API...
Linux_C_Jecon<2> 1:11:45
设计
c/c++_xiaoxiao(1) 1:11:54
比如说,如何设计一个多线程
c/c++_xiaoxiao(1) 1:11:58
还是,多线程如何用。。
c/c++_xiaoxiao(1) 1:12:03
你现在卡在哪个环节
Linux_C_Jecon<2> 1:12:06
多线程如何用
Linux_C_Jecon<2> 1:12:17
堵塞什么的
c/c++_xiaoxiao(1) 1:12:17
win/linux/mac?
c/c++_xiaoxiao(1) 1:12:22
额。。
Linux_C_Jecon<2> 1:12:24
linux
c/c++_xiaoxiao(1) 1:12:24
那个啊。。。
Linux_C_Jecon<2> 1:12:27
ubuntu
Linux_C_Jecon<2> 1:12:28
恩
c/c++_xiaoxiao(1) 1:13:16
多处理器编程的艺术
我记得是用java做的demo?
Linux_C_Jecon<2> 1:13:36
3Q
Linux_C_Jecon<2> 1:13:48
Java的会
Linux_C_Jecon<2> 1:13:59
关键是有API NND
c/c++_xiaoxiao(1) 1:14:16
额。。
c/c++_xiaoxiao(1) 1:14:24
API无外乎是互斥 自旋 读写
c/c++_xiaoxiao(1) 1:14:36
一般来说,你只会看到2把锁 互斥 读写
c/c++_xiaoxiao(1) 1:14:41
然后c的线程API
c/c++_xiaoxiao(1) 1:14:43
一律是这样的
Linux_C_Jecon<2> 1:14:49
读者写者的做法吗
c/c++_xiaoxiao(1) 1:15:04
status fun(callback, arg)
c/c++_xiaoxiao(1) 1:15:21
这是一个线程启动函数
c/c++_xiaoxiao(1) 1:15:26
然后一个线程函数
c/c++_xiaoxiao(1) 1:15:27
是这样的
c/c++_xiaoxiao(1) 1:15:32
statuc thread(arg)
c/c++_xiaoxiao(1) 1:15:42
也就是说,他只接受一个参数,然后返回一个状态
c/c++_xiaoxiao(1) 1:15:45
。。。
c/c++_xiaoxiao(1) 1:15:48
和java没啥区别啊
c/c++_xiaoxiao(1) 1:15:58
嗯,api就是读写锁和互斥锁了
Linux_C_Jecon<2> 1:16:09
恩
Linux_C_Jecon<2> 1:16:15
哦
c/c++_xiaoxiao(1) 1:16:29
至于那些调整线程属性的参数
c/c++_xiaoxiao(1) 1:16:33
你一律可以无视。。。
c/c++_xiaoxiao(1) 1:16:41
你要坚信,OS的自动调整比你手工设置好
c/c++_xiaoxiao(1) 1:16:57
除非你的业务环境非常特殊,所以这类参数一律传NULL就是了
c/c++_xiaoxiao(1) 1:17:28
pthread_create(attr, callback, callback_arg, thread_id);
c/c++_xiaoxiao(1) 1:17:47
第一个参数设置线程属性,然后是线程启动函数,线程启动函数的参数,线程的id
c/c++_xiaoxiao(1) 1:17:55
几乎所有的系统,线程都是这几个参数
c/c++_xiaoxiao(1) 1:18:13
关键是,你得看他的callback的函数声明,必须严格和他一样否则,小心core。。
Linux_C_Jecon<2> 1:18:34
恩
Linux_C_Jecon<2> 1:18:43
哦
Linux_C_Jecon<2> 1:19:12
有这方面的Demo或者是书籍吗
c/c++_xiaoxiao(1) 1:19:14
主要是,ABI的不一致,可能导致堆栈不平衡
c/c++_xiaoxiao(1) 1:19:22
demo?
Linux_C_Jecon<2> 1:19:26
额,abi是什么
c/c++_xiaoxiao(1) 1:19:35
...
c/c++_xiaoxiao(1) 1:19:38
我写个例子吧
c/c++_xiaoxiao(1) 1:19:39
比如
c/c++_xiaoxiao(1) 1:19:44
void fun(int a, int b);
c/c++_xiaoxiao(1) 1:19:48
void bar(int a);
Linux_C_Jecon<2> 1:19:49
恩
c/c++_xiaoxiao(1) 1:20:04
当传函数指针的时候,为什么编译器会告诉你,函数不匹配
c/c++_xiaoxiao(1) 1:20:14
表面看起来,是声明不同
c/c++_xiaoxiao(1) 1:20:14
对吧
c/c++_xiaoxiao(1) 1:20:22
但是,函数,本质就是一个地址
c/c++_xiaoxiao(1) 1:20:23
对吧
c/c++_xiaoxiao(1) 1:20:34
声明不同反正都是一个地址,报错干啥
c/c++_xiaoxiao(1) 1:20:40
因为,ABI不一致
c/c++_xiaoxiao(1) 1:20:54
你看了2天android的那2B虚拟机的汇编了
c/c++_xiaoxiao(1) 1:20:58
大概知道点了吧
Linux_C_Jecon<2> 1:21:03
恩知道
c/c++_xiaoxiao(1) 1:21:13
比如,我用内存传参
c/c++_xiaoxiao(1) 1:21:28
本来,我接受的函数参数是2个
c/c++_xiaoxiao(1) 1:21:35
那么,我就会去内存里面,读2个值出来
c/c++_xiaoxiao(1) 1:21:38
对吧
c/c++_xiaoxiao(1) 1:21:45
你现在,给我的函数,其实只有一个参数
c/c++_xiaoxiao(1) 1:21:52
但是,对他来说,他是不知道的
c/c++_xiaoxiao(1) 1:21:58
所以,我依旧会读2个参数。
c/c++_xiaoxiao(1) 1:21:59
对不对?
c/c++_xiaoxiao(1) 1:22:05
第二个参数读到啥了。。。
Linux_C_Jecon<2> 1:22:12
恩
c/c++_xiaoxiao(1) 1:22:11
越界了。。
c/c++_xiaoxiao(1) 1:22:13
是吧。
Linux_C_Jecon<2> 1:22:26
是的
c/c++_xiaoxiao(1) 1:22:43
这种行为,可能导致崩溃吧
c/c++_xiaoxiao(1) 1:22:46
这个就叫做abi不一直
c/c++_xiaoxiao(1) 1:22:48
不一致
Linux_C_Jecon<2> 1:22:55
哦
c/c++_xiaoxiao(1) 1:23:06
再举个例子
c/c++_xiaoxiao(1) 1:23:09
我有4个寄存器
c/c++_xiaoxiao(1) 1:23:23
我和你约定,我的头4个参数,都用寄存器传参,依次用寄存器R1 R2 R3 R4
c/c++_xiaoxiao(1) 1:23:34
然后,你给我传参的时候,你实质上是这样传递的
c/c++_xiaoxiao(1) 1:23:40
4个参数依次用R4 R3 R2 R1...
c/c++_xiaoxiao(1) 1:23:46
那么,我读到的4个参数,变成啥了。。
Linux_C_Jecon<2> 1:23:59
认不到
c/c++_xiaoxiao(1) 1:24:16
但是,我压根不知道啊
Linux_C_Jecon<2> 1:24:23
是的
c/c++_xiaoxiao(1) 1:24:23
我以为,你传递的方式和我要求的一致
c/c++_xiaoxiao(1) 1:24:34
所以,解析的时候,就会解释出错误的值
Linux_C_Jecon<2> 1:24:40
恩
c/c++_xiaoxiao(1) 1:24:42
比如,第一个参数,本来是int,最后一个参数是一个pointer
c/c++_xiaoxiao(1) 1:24:56
你的本意是传一个0,传一个0xff
c/c++_xiaoxiao(1) 1:25:14
结果,我把0xff当作int了,解释成了255,把0当作指针了,解析成了NULL
c/c++_xiaoxiao(1) 1:25:17
那么,悲剧了吧
Linux_C_Jecon<2> 1:25:23
恩
c/c++_xiaoxiao(1) 1:25:31
这个也叫做ABI不一致
c/c++_xiaoxiao(1) 1:25:37
当然,ABI基本上是由编译器在维护的
Linux_C_Jecon<2> 1:25:38
差不多
c/c++_xiaoxiao(1) 1:25:49
但是,有声明的
c/c++_xiaoxiao(1) 1:25:53
比如你在windows下看到的
c/c++_xiaoxiao(1) 1:25:57
stdcall
c/c++_xiaoxiao(1) 1:25:58
cdecl
c/c++_xiaoxiao(1) 1:26:00
thiscall
c/c++_xiaoxiao(1) 1:26:06
这个就是ABI
Linux_C_Jecon<2> 1:26:10
哦
c/c++_xiaoxiao(1) 1:26:11
他们约束了,一个函数的参数如何传递
c/c++_xiaoxiao(1) 1:26:14
在linux下
c/c++_xiaoxiao(1) 1:26:23
有__attribute__(asmlinkage(....))
c/c++_xiaoxiao(1) 1:26:32
attribute里面的我忘记具体如何的了。
c/c++_xiaoxiao(1) 1:26:37
他也是约定传参规范的。
Linux_C_Jecon<2> 1:26:42
额
c/c++_xiaoxiao(1) 1:26:50
貌似是这样的
c/c++_xiaoxiao(1) 1:26:52
反正有个宏。。
Linux_C_Jecon<2> 1:26:55
这样啊,我倒是没去关注编译器的问题
Linux_C_Jecon<2> 1:27:04
恩
c/c++_xiaoxiao(1) 1:27:06
如果某个函数的一个参数
c/c++_xiaoxiao(1) 1:27:07
是一个callback
c/c++_xiaoxiao(1) 1:27:13
然后,他的声明里面有这些东西
c/c++_xiaoxiao(1) 1:27:19
你实现的函数,没有写这个。
c/c++_xiaoxiao(1) 1:27:28
那么,编译器就不会去生成那个特殊的调用约定
c/c++_xiaoxiao(1) 1:27:37
对于c代码来说,这是一个警告,对于c++来说,这是一个错误
c/c++_xiaoxiao(1) 1:27:44
如果,你无视这个,强转。。
Linux_C_Jecon<2> 1:27:47
恩
c/c++_xiaoxiao(1) 1:27:50
你说会有啥后果。。
c/c++_xiaoxiao(1) 1:28:29
这里还没扯到堆栈平衡。。。只是讲了ABI的传参部分,ABI还有一个部分是堆栈平衡
c/c++_xiaoxiao(1) 1:28:33
又谁来负责清理堆栈
c/c++_xiaoxiao(1) 1:28:59
比如,传参用内存传参的话
c/c++_xiaoxiao(1) 1:29:05
谁来销毁这些内存呢?
c/c++_xiaoxiao(1) 1:29:11
ABI的类型决定的
Linux_C_Jecon<2> 1:29:17
哦
c/c++_xiaoxiao(1) 1:29:31
因为,现在的编译器模型。。
c/c++_xiaoxiao(1) 1:29:36
返回地址是在这些内存上的。。
c/c++_xiaoxiao(1) 1:29:50
所以,如果ABI匹配出错了,那么函数的返回地址就会解析错
c/c++_xiaoxiao(1) 1:29:56
这个时候,就会出现core了。
c/c++_xiaoxiao(1) 1:30:05
或者是,函数的栈不知道飞哪里去了。
Linux_C_Jecon<2> 1:30:20
恩
c/c++_xiaoxiao(1) 1:30:21
当然,你还可以手工的让函数的返回地址解析出错。。
c/c++_xiaoxiao(1) 1:30:25
答案就是,数组越界。。。
c/c++_xiaoxiao(1) 1:30:34
直接覆盖掉那个函数的返回地址
c/c++_xiaoxiao(1) 1:30:51
和ABI不匹配不同,他是覆盖了返回地址,ABI不匹配是返回地址本身是对的,但是解析的时候,解析到其他位置去了
c/c++_xiaoxiao(1) 1:31:02
这个,一般出现在用汇编手写函数的时候
Linux_C_Jecon<2> 1:31:14
哦
c/c++_xiaoxiao(1) 1:31:19
因为,汇编手写函数的时候,很容易忘记清理函数栈。。
c/c++_xiaoxiao(1) 1:31:31
对于android上的应用
c/c++_xiaoxiao(1) 1:31:35
最容易出现问题的就是
c/c++_xiaoxiao(1) 1:31:39
你们以后做hook
Linux_C_Jecon<2> 1:31:48
恩
c/c++_xiaoxiao(1) 1:31:48
比如,你想拦截用户打电话
c/c++_xiaoxiao(1) 1:31:54
假如
c/c++_xiaoxiao(1) 1:31:59
你又找不到,系统提供了一个event给你
c/c++_xiaoxiao(1) 1:32:14
那么,你唯一的做法,就是劫持掉那个打电话的API
Linux_C_Jecon<2> 1:32:24
恩
c/c++_xiaoxiao(1) 1:32:26
但是,你又不能改系统代码。。。
c/c++_xiaoxiao(1) 1:32:32
因为,你的app要通用。。
c/c++_xiaoxiao(1) 1:32:41
否则,只能自家的ROM上跑
c/c++_xiaoxiao(1) 1:32:48
所以,你得改机器码。。。
c/c++_xiaoxiao(1) 1:33:01
这个时候,就得汇编写那么一小块的跳转代码了。
c/c++_xiaoxiao(1) 1:33:12
那个时候,就需要那种恶心问题了
Linux_C_Jecon<2> 1:33:17
恩
Linux_C_Jecon<2> 1:33:35
哪种恶心的问题
Linux_C_Jecon<2> 1:33:38
汇编吗
c/c++_xiaoxiao(1) 1:33:40
所以,线程的启动函数,你保证,参数类型一致就够了。
Linux_C_Jecon<2> 1:33:44
写汇编吗
c/c++_xiaoxiao(1) 1:33:44
嗯。。
c/c++_xiaoxiao(1) 1:33:48
嗯。。
Linux_C_Jecon<2> 1:33:52
恩
c/c++_xiaoxiao(1) 1:34:06
其他,没啥了。
c/c++_xiaoxiao(1) 1:34:13
其他就是所谓的加mutex了。。
Linux_C_Jecon<2> 1:34:18
哦
c/c++_xiaoxiao(1) 1:34:18
记得上各种mutex就好了
Linux_C_Jecon<2> 1:34:23
这个倒是学过
Linux_C_Jecon<2> 1:34:38
如果要处理非堵塞的问题,怎么做
c/c++_xiaoxiao(1) 1:34:45
非阻塞?
c/c++_xiaoxiao(1) 1:34:46
具体
c/c++_xiaoxiao(1) 1:35:00
来个场景
Linux_C_Jecon<2> 1:35:04
肯定是会有堵塞,非堵塞中肯定是会有堵塞的 类似JAVA 的NIO
c/c++_xiaoxiao(1) 1:35:11
你是说IO么?
Linux_C_Jecon<2> 1:35:15
恩
c/c++_xiaoxiao(1) 1:35:16
还是说线程本身
Linux_C_Jecon<2> 1:35:21
线程
c/c++_xiaoxiao(1) 1:35:27
线程本身就是非阻塞的啊,除非你上mutex,否则一定异步
Linux_C_Jecon<2> 1:35:30
多个线程共享一个临界区
c/c++_xiaoxiao(1) 1:35:37
那就上mutex呗。。
c/c++_xiaoxiao(1) 1:35:44
进临界区加mutex,出来干掉mutex
Linux_C_Jecon<2> 1:36:06
那如果线程在临界区卡住了呢
Linux_C_Jecon<2> 1:36:18
也就是堵住了临界区的入口出不去了
c/c++_xiaoxiao(1) 1:36:18
...这种问题
c/c++_xiaoxiao(1) 1:36:25
怎么会呢?
c/c++_xiaoxiao(1) 1:36:28
除非你在里面死循环了。
Linux_C_Jecon<2> 1:36:32
比如发送异常的情况
c/c++_xiaoxiao(1) 1:36:35
或者死锁了。
c/c++_xiaoxiao(1) 1:36:40
异常么?
Linux_C_Jecon<2> 1:36:45
对 就是说死锁
Linux_C_Jecon<2> 1:36:46
恩恩
Linux_C_Jecon<2> 1:36:47
是的
c/c++_xiaoxiao(1) 1:36:48
异常你catch了,他会自动帮你释放掉的。
c/c++_xiaoxiao(1) 1:36:55
死锁的话,那个是设计问题了。
Linux_C_Jecon<2> 1:37:01
哦
c/c++_xiaoxiao(1) 1:37:21
准确点说,是catch了以后,你得记得释放临界区。。
Linux_C_Jecon<2> 1:37:27
恩
Linux_C_Jecon<2> 1:37:36
让线程进入等待
c/c++_xiaoxiao(1) 1:37:35
所以,你在临界区里面抛异常的时候,一定记得提示额外信息。。
Linux_C_Jecon<2> 1:37:46
恩
c/c++_xiaoxiao(1) 1:37:46
其实,最好是临界区的里面别抛异常。。
c/c++_xiaoxiao(1) 1:37:57
本身,临界区就应该尽量避免复杂化
c/c++_xiaoxiao(1) 1:38:03
里面抛异常,里面接。。
Linux_C_Jecon<2> 1:38:04
这个倒是很难保证啊
c/c++_xiaoxiao(1) 1:38:08
这是基本的原则
Linux_C_Jecon<2> 1:38:14
额
c/c++_xiaoxiao(1) 1:38:19
那就里面抛,里面接,不要让异常从临界区跑出来
Linux_C_Jecon<2> 1:38:26
恩
c/c++_xiaoxiao(1) 1:38:39
一般来说
c/c++_xiaoxiao(1) 1:38:48
非系统资源导致的异常
c/c++_xiaoxiao(1) 1:38:58
很难在临界区抛出来吧。。代码bug除外
Linux_C_Jecon<2> 1:39:06
是的
c/c++_xiaoxiao(1) 1:39:06
代码bug那个可以改,测试的时候就应该能发现。
Linux_C_Jecon<2> 1:39:14
除非把异常往外抛了
c/c++_xiaoxiao(1) 1:39:15
系统异常了,我觉得。。。
c/c++_xiaoxiao(1) 1:39:31
app就算多活那么一会,过会也得死。。
c/c++_xiaoxiao(1) 1:39:32
没错吧。。
Linux_C_Jecon<2> 1:39:39
是
c/c++_xiaoxiao(1) 1:39:44
就好比,你在java里面
Linux_C_Jecon<2> 1:39:46
直接死机了
c/c++_xiaoxiao(1) 1:39:48
new失败了。。
c/c++_xiaoxiao(1) 1:39:56
这个异常,你接过来,其实,你真的做不了啥了。
c/c++_xiaoxiao(1) 1:40:01
没错吧。。。
Linux_C_Jecon<2> 1:40:04
是
c/c++_xiaoxiao(1) 1:40:16
所以,你关注几个重点异常就好了
c/c++_xiaoxiao(1) 1:40:18
1. socket
c/c++_xiaoxiao(1) 1:40:21
2. 文件io
c/c++_xiaoxiao(1) 1:40:37
文件io异常,要么是没权限,要么是目录不存在,要么是磁盘满了。。
Linux_C_Jecon<2> 1:40:45
恩
c/c++_xiaoxiao(1) 1:40:45
我觉得,这几个情况,编码上就能干掉吧。。
c/c++_xiaoxiao(1) 1:40:52
check一把就好了
Linux_C_Jecon<2> 1:41:00
恩
c/c++_xiaoxiao(1) 1:41:05
至于socket,自己抓个异常,看看socket状态,也出来了吧
Linux_C_Jecon<2> 1:41:16
恩
c/c++_xiaoxiao(1) 1:41:28
那么,系统资源异常,也基本能干掉了,说白了,最后的问题就是你那把锁,设计得多复杂了。。
Linux_C_Jecon<2> 1:41:30
我想用C写个多线程的
Linux_C_Jecon<2> 1:41:35
恩
Linux_C_Jecon<2> 1:41:42
问你个问题
Linux_C_Jecon<2> 1:41:48
C有线程池吗
c/c++_xiaoxiao(1) 1:41:57
没有。。
c/c++_xiaoxiao(1) 1:41:58
自己实现。。
Linux_C_Jecon<2> 1:42:15
额
Linux_C_Jecon<2> 1:42:16
好吧
c/c++_xiaoxiao(1) 1:42:19
其实锁的问题比你想象中简单的多。。
c/c++_xiaoxiao(1) 1:42:29
因为,绝大部分的锁,可以被封装掉
Linux_C_Jecon<2> 1:42:37
恩
c/c++_xiaoxiao(1) 1:42:52
当然,代价就是性能下降了,因为每次调用,他里面必然有加锁解锁
c/c++_xiaoxiao(1) 1:43:00
线程池这个玩意。。。
c/c++_xiaoxiao(1) 1:43:05
比你想的作用要小
c/c++_xiaoxiao(1) 1:43:22
线程池无外乎就是,开一堆的线程,要用的时候丢个任务进去,然后88
Linux_C_Jecon<2> 1:43:27
恩是的
c/c++_xiaoxiao(1) 1:43:34
说实话,开个线程的开销其实不大。。
Linux_C_Jecon<2> 1:43:49
线程池主要是管理线程
c/c++_xiaoxiao(1) 1:43:49
然后,丢个任务进去,他啥时候做你还不知道,对吧
Linux_C_Jecon<2> 1:44:05
看怎么设计了
c/c++_xiaoxiao(1) 1:44:07
线程池的根本目的是,减少线程开销
Linux_C_Jecon<2> 1:44:13
是
c/c++_xiaoxiao(1) 1:44:23
线程的开销,其实不大。。
c/c++_xiaoxiao(1) 1:44:24
真不大。。。
Linux_C_Jecon<2> 1:44:29
当有空闲的线程,通过线程池调用
c/c++_xiaoxiao(1) 1:44:28
你想得太复杂了
c/c++_xiaoxiao(1) 1:44:41
你不去做服务端上的高并发,很难遇上需要线程池
Linux_C_Jecon<2> 1:44:43
你一般不用线程池吗
c/c++_xiaoxiao(1) 1:44:48
但是,服务端的高并发。。。
c/c++_xiaoxiao(1) 1:44:54
一般线程创建了,就闲不下来了。。
Linux_C_Jecon<2> 1:45:00
是的
c/c++_xiaoxiao(1) 1:45:03
所以,压根不会出现空闲线程,需要管理的情况
c/c++_xiaoxiao(1) 1:45:20
其实线程池的根本目的,无外乎是怕你有个任务,很快完成了,然后做完,线程88了
c/c++_xiaoxiao(1) 1:45:28
你保证,他无限制的接任务就好了。。。
Linux_C_Jecon<2> 1:45:53
恩 对的
c/c++_xiaoxiao(1) 1:45:55
除非你去写一个基础库,提供给别人用
c/c++_xiaoxiao(1) 1:46:00
否则,线程池这种很复杂的东西
c/c++_xiaoxiao(1) 1:46:03
你完全看屏蔽掉
c/c++_xiaoxiao(1) 1:46:07
因为,你知道自己的业务是啥
c/c++_xiaoxiao(1) 1:46:12
你完全可以一个for循环接任务。。。
c/c++_xiaoxiao(1) 1:46:14
接到死。。
Linux_C_Jecon<2> 1:46:16
恩
c/c++_xiaoxiao(1) 1:46:29
线程池的问题是,他是一个基础库,他没法知道具体的业务。。
c/c++_xiaoxiao(1) 1:46:35
所以才会抽象级别那么高。。
c/c++_xiaoxiao(1) 1:47:05
对于频繁的短任务,其实真的设计里面,很少会出现,大量频繁的需要异步调用的短任务吧。。。
Linux_C_Jecon<2> 1:47:06
恩 他只要管理好线程就行了,比如某个线程做完事 继续等待
c/c++_xiaoxiao(1) 1:47:13
其实,同步调用完全够用了吧
Linux_C_Jecon<2> 1:47:17
是的
c/c++_xiaoxiao(1) 1:47:19
你不会,是个函数你就想异步调用下吧
c/c++_xiaoxiao(1) 1:47:26
绝大部分的逻辑,你可以在当前线程做了吧
c/c++_xiaoxiao(1) 1:47:35
耗时的,无外乎是IO(网络,本地)
c/c++_xiaoxiao(1) 1:47:39
大不了走异步io就是了
Linux_C_Jecon<2> 1:47:45
哦
c/c++_xiaoxiao(1) 1:47:53
然后callback处理回调完成的事件,和信号一样
Linux_C_Jecon<2> 1:48:00
恩
c/c++_xiaoxiao(1) 1:48:04
他自动在完成的时候,调用你传进去的callback
c/c++_xiaoxiao(1) 1:48:20
所以说,线程池那个东西,本身不是刚需。。
c/c++_xiaoxiao(1) 1:48:27
就看你如何设计自己的代码了。
c/c++_xiaoxiao(1) 1:48:34
当然,去写个线程池也挺好的。
Linux_C_Jecon<2> 1:49:00
如果我写个游戏服务器的话,是会遇到线程池的问题
Linux_C_Jecon<2> 1:49:01
恩
c/c++_xiaoxiao(1) 1:49:10
不用啊。。
Linux_C_Jecon<2> 1:49:15
为啥啊
linux_电工(79127502) 1:49:18
起床尿尿了
Linux_C_Jecon<2> 1:49:20
我写私服
c/c++_xiaoxiao(1) 1:49:27
你觉得线程池放在哪里部分。。
c/c++_xiaoxiao(1) 1:49:31
网络并发?
Linux_C_Jecon<2> 1:49:35
是
c/c++_xiaoxiao(1) 1:49:39
还是各种事件处理?
c/c++_xiaoxiao(1) 1:49:44
事件处理可以同步掉吧。。
Linux_C_Jecon<2> 1:49:48
并发
2013-04-24
c/c++_xiaoxiao(1) 1:49:56
并发,那个为什么要线程池?
Linux_C_Jecon<2> 1:50:10
恩 处理不同的事件啊
c/c++_xiaoxiao(1) 1:50:11
我开1个线程,死循环在哪里接socket事件就好了
Linux_C_Jecon<2> 1:50:17
哦
c/c++_xiaoxiao(1) 1:50:18
接到以后,dispatch给不同的线程
c/c++_xiaoxiao(1) 1:50:30
A线程,专门处理用户移动
c/c++_xiaoxiao(1) 1:50:39
B线程,专门处理用户释放技能
c/c++_xiaoxiao(1) 1:50:40
...
Linux_C_Jecon<2> 1:50:53
恩
c/c++_xiaoxiao(1) 1:51:07
接到socket事件,把socket包丢给dispatch线程,dispatch线程简单解包,看事件类型,丢给ABCD.
Linux_C_Jecon<2> 1:51:21
如果是1000人在线要怎么处理
Linux_C_Jecon<2> 1:51:39
你的意思是说消息队列吗
c/c++_xiaoxiao(1) 1:51:39
你觉得dispatch太慢的话,dispatch按照包的id,id % 3 == 1 id % 3 ==0 id %3 == 2丢给1 2 3这3个线程
c/c++_xiaoxiao(1) 1:51:47
这3个线程,再丢给下面的线程去处理
c/c++_xiaoxiao(1) 1:51:52
不用啊,一路dispatch就好了啊
Linux_C_Jecon<2> 1:51:54
哦
c/c++_xiaoxiao(1) 1:51:58
一个生产者,多个消费者啊
Linux_C_Jecon<2> 1:52:03
哦哦
c/c++_xiaoxiao(1) 1:52:05
你觉得,这种模式还太慢的话
c/c++_xiaoxiao(1) 1:52:14
消费者再分层
c/c++_xiaoxiao(1) 1:52:16
没问题吧
Linux_C_Jecon<2> 1:52:26
明白了
c/c++_xiaoxiao(1) 1:52:31
消费者在当前自己这一环节,他又是一个生产者的身份
linux_电工(79127502) 1:52:31
Linux_C_Jecon<2> 1:52:37
生产者是主线程把控的
c/c++_xiaoxiao(1) 1:52:37
继续往下dispatch
c/c++_xiaoxiao(1) 1:52:42
嗯
linux_电工(79127502) 1:52:42
你们两不打算睡觉了吗
c/c++_xiaoxiao(1) 1:52:49
第一个生产者,处理socket事件就好了
Linux_C_Jecon<2> 1:52:56
恩
c/c++_xiaoxiao(1) 1:53:02
他只接socket实践,不对socket事件做任何处理
c/c++_xiaoxiao(1) 1:53:06
抓到了,往下丢
c/c++_xiaoxiao(1) 1:53:09
收包啥的,其他人去做
Linux_C_Jecon<2> 1:53:13
恩
c/c++_xiaoxiao(1) 1:53:23
然后,初步解包,按照包里面的事件不同
c/c++_xiaoxiao(1) 1:53:27
丢给不同的thread去做处理
c/c++_xiaoxiao(1) 1:53:33
需要线程池么?
Linux_C_Jecon<2> 1:53:35
再分发
c/c++_xiaoxiao(1) 1:53:39
嗯
c/c++_xiaoxiao(1) 1:53:41
需要线程池么。。
c/c++_xiaoxiao(1) 1:53:45
一个生产者消费者搞定了。。
c/c++_xiaoxiao(1) 1:53:52
你觉得太慢就继续拆生产者消费模型
c/c++_xiaoxiao(1) 1:53:56
把类型细分。。
Linux_C_Jecon<2> 1:54:01
线程池的作用跟主线程的作用有点像
c/c++_xiaoxiao(1) 1:54:11
细分还不够,同一个类型的事件,就继续拆分
c/c++_xiaoxiao(1) 1:54:14
按照事件ID拆分
Linux_C_Jecon<2> 1:54:18
嗯呢
c/c++_xiaoxiao(1) 1:54:24
事件是3的倍数的,给线程3
c/c++_xiaoxiao(1) 1:54:29
2的倍数的,给线程2
c/c++_xiaoxiao(1) 1:54:31
其他的,给线程1
c/c++_xiaoxiao(1) 1:54:32
可以吧
c/c++_xiaoxiao(1) 1:54:41
再不行,加机器吧。。。。
c/c++_xiaoxiao(1) 1:54:50
需要线程池么。。
Linux_C_Jecon<2> 1:54:51
恩
c/c++_xiaoxiao(1) 1:54:55
我前面说过了
Linux_C_Jecon<2> 1:54:56
不需要
Linux_C_Jecon<2> 1:55:01
直接用缓存存储
c/c++_xiaoxiao(1) 1:55:02
线程池本身是作为一个高抽象的东西
c/c++_xiaoxiao(1) 1:55:08
他不知道你的业务具体的类型
c/c++_xiaoxiao(1) 1:55:19
导致,他必须支持通用的任务
每个业务每个缓存区
c/c++_xiaoxiao(1) 1:55:25
所以才会有那么个管理方式
Linux_C_Jecon<2> 1:55:32
恩
c/c++_xiaoxiao(1) 1:55:33
当你的业务本身是已知的时候
c/c++_xiaoxiao(1) 1:55:37
你完全没必要用线程池
c/c++_xiaoxiao(1) 1:55:42
自己对线程进行封装
c/c++_xiaoxiao(1) 1:55:45
该做啥做啥就好了
Linux_C_Jecon<2> 1:55:49
恩
c/c++_xiaoxiao(1) 1:56:05
当然,可能不如线程池经济,但是,简单的设计,好处就是容易排查问题
c/c++_xiaoxiao(1) 1:56:09
线程池的话,某个业务出问题了
c/c++_xiaoxiao(1) 1:56:13
你都不知道这个业务跑在哪里!
c/c++_xiaoxiao(1) 1:56:18
你知道么。。
Linux_C_Jecon<2> 1:56:22
不知道
c/c++_xiaoxiao(1) 1:56:23
排查恶心吧
Linux_C_Jecon<2> 1:56:37
经常发生这种问题
c/c++_xiaoxiao(1) 1:56:54
通用必然带来高抽象,那么带来的副作用就是排查问题复杂度增加
Linux_C_Jecon<2> 1:57:03
我们JAVA用的是XMPP服务下OPENFIRE框架,抱异常的时候,排查很痛苦
Linux_C_Jecon<2> 1:57:16
是的
c/c++_xiaoxiao(1) 1:57:23
所以,你看很多现在的框架
c/c++_xiaoxiao(1) 1:57:24
和项目
c/c++_xiaoxiao(1) 1:57:27
都提倡轻量级
c/c++_xiaoxiao(1) 1:57:32
他只提供一个分发接口
c/c++_xiaoxiao(1) 1:57:34
下面的东西
c/c++_xiaoxiao(1) 1:57:35
都自己做
c/c++_xiaoxiao(1) 1:57:36
对吧
Linux_C_Jecon<2> 1:57:45
对的
c/c++_xiaoxiao(1) 1:57:47
就是因为,具体的业务,自己最熟悉,自己好设计。
c/c++_xiaoxiao(1) 1:57:51
小心设计过度。。。
Linux_C_Jecon<2> 1:58:04
我很早以前用的是。。触发器
c/c++_xiaoxiao(1) 1:58:06
不过,作为线程池这种东西,咋说呢,自己去设计一个,也未必是坏事
Linux_C_Jecon<2> 1:58:09
观察者模式
Linux_C_Jecon<2> 1:58:11
恩
c/c++_xiaoxiao(1) 1:58:23
你设计的越加复杂,越加坑。
c/c++_xiaoxiao(1) 1:58:26
对于小规模的代码
c/c++_xiaoxiao(1) 1:58:36
大规模的代码,设计模式是有必要的,因为,思路可以清晰化,小规模的代码。。
c/c++_xiaoxiao(1) 1:58:44
设计模式,除了增加复杂性,我真不知道还能干啥。。。
Linux_C_Jecon<2> 1:58:54
也不是小规模的代码
c/c++_xiaoxiao(1) 1:58:57
就好比,我就一个cpp,200行,我有个全局变量,都不对外暴露
Linux_C_Jecon<2> 1:59:01
预计挺大的
c/c++_xiaoxiao(1) 1:59:03
我写个单例,有意义么。。
c/c++_xiaoxiao(1) 1:59:13
嗯,我只是说这个事而已
Linux_C_Jecon<2> 1:59:23
要是能承受的住10W的话,不用线程池好像不好管理
Linux_C_Jecon<2> 1:59:28
恩
c/c++_xiaoxiao(1) 1:59:34
10W并发,一般不考虑一台机器了。。。
Linux_C_Jecon<2> 1:59:41
额
c/c++_xiaoxiao(1) 1:59:46
榨干机器性能
c/c++_xiaoxiao(1) 1:59:57
不一定要这样选择
Linux_C_Jecon<2> 2:00:01
哦
c/c++_xiaoxiao(1) 2:00:01
简单点说
c/c++_xiaoxiao(1) 2:00:04
如果你一个业务
Linux_C_Jecon<2> 2:00:07
看集群了
c/c++_xiaoxiao(1) 2:00:06
你有10W的并发了
c/c++_xiaoxiao(1) 2:00:09
我不信
c/c++_xiaoxiao(1) 2:00:10
一台机器
c/c++_xiaoxiao(1) 2:00:12
你能跑完所有业务
Linux_C_Jecon<2> 2:00:24
看硬件的问题了
c/c++_xiaoxiao(1) 2:00:28
就算你能跑完。。你这台机器上的业务部署,得多复杂。。。
Linux_C_Jecon<2> 2:00:35
是的
c/c++_xiaoxiao(1) 2:00:41
你能拆么。。
Linux_C_Jecon<2> 2:00:48
拆不了
拆到N台机器上去。。。
Linux_C_Jecon<2> 2:00:54
可以试试
c/c++_xiaoxiao(1) 2:00:56
那真是设计问题了。。
c/c++_xiaoxiao(1) 2:01:01
一台机器撑10W并发。。。
c/c++_xiaoxiao(1) 2:01:08
这个概念。。。。
Linux_C_Jecon<2> 2:01:11
是说同样的模块拆分吗
c/c++_xiaoxiao(1) 2:01:16
我真的只能说,NB..
Linux_C_Jecon<2> 2:01:21
那倒是可以
c/c++_xiaoxiao(1) 2:01:22
简单点说
c/c++_xiaoxiao(1) 2:01:28
当你真的有10W并发的时候
Linux_C_Jecon<2> 2:01:33
我再做个代理
c/c++_xiaoxiao(1) 2:01:32
你的业务绝对不是简单的
Linux_C_Jecon<2> 2:01:37
恩
c/c++_xiaoxiao(1) 2:01:37
你肯定有很多复杂的功能
c/c++_xiaoxiao(1) 2:01:44
你一台机器,绝对跑不完
c/c++_xiaoxiao(1) 2:01:48
那么,你这个时候,要考虑的是
c/c++_xiaoxiao(1) 2:01:53
如何把业务分摊到不同的机器上去
Linux_C_Jecon<2> 2:01:57
哦
c/c++_xiaoxiao(1) 2:02:05
不要求每台机器都是全能的
Linux_C_Jecon<2> 2:02:08
这样啊
c/c++_xiaoxiao(1) 2:02:15
要求,每台机器专精一项或者是一个环节的业务
Linux_C_Jecon<2> 2:02:17
类似微信的做法吗
Linux_C_Jecon<2> 2:02:23
恩
c/c++_xiaoxiao(1) 2:02:27
然后,多台机器组成流水线
c/c++_xiaoxiao(1) 2:02:31
拼出一个完整业务
c/c++_xiaoxiao(1) 2:02:36
当然,如果你业务真的非常简单
Linux_C_Jecon<2> 2:02:37
哦
c/c++_xiaoxiao(1) 2:02:41
一台机器可以跑完,但是要求高并发
c/c++_xiaoxiao(1) 2:02:44
你的设计应该是
c/c++_xiaoxiao(1) 2:02:55
再做一个生产者,消费者
c/c++_xiaoxiao(1) 2:03:04
这个生产者叫做网关
c/c++_xiaoxiao(1) 2:03:13
他去做dispatch,给下面的机器,每台机器复杂一部分的业务
Linux_C_Jecon<2> 2:03:17
分发数据包到消费者手里
Linux_C_Jecon<2> 2:03:19
类似代理吗
c/c++_xiaoxiao(1) 2:03:23
嗯。
c/c++_xiaoxiao(1) 2:03:27
这个叫做网关。。。。
Linux_C_Jecon<2> 2:03:29
ngnix的做法
Linux_C_Jecon<2> 2:03:30
恩
Linux_C_Jecon<2> 2:03:34
负载均衡
c/c++_xiaoxiao(1) 2:03:41
看你的业务模型了
Linux_C_Jecon<2> 2:03:46
哦
c/c++_xiaoxiao(1) 2:03:45
不要想着全能
c/c++_xiaoxiao(1) 2:03:49
同样
c/c++_xiaoxiao(1) 2:03:51
你要榨干机器。。
c/c++_xiaoxiao(1) 2:03:59
某项业务不吃cpu,吃网络
c/c++_xiaoxiao(1) 2:04:08
某项业务不吃网络,吃cpu
c/c++_xiaoxiao(1) 2:04:16
如果你拆分的好,你完全可以。。。
c/c++_xiaoxiao(1) 2:04:18
懂我意思吧
Linux_C_Jecon<2> 2:04:27
恩
c/c++_xiaoxiao(1) 2:04:27
某些机器,部署A B业务,某些机器部署C业务
Linux_C_Jecon<2> 2:04:29
懂了
c/c++_xiaoxiao(1) 2:04:33
一样可以榨干系统性能
c/c++_xiaoxiao(1) 2:04:40
何必一台机器跑完ABCD...呢
c/c++_xiaoxiao(1) 2:04:43
徒增设计复杂性。。。
c/c++_xiaoxiao(1) 2:04:51
还有调试。。。
c/c++_xiaoxiao(1) 2:04:54
排查
Linux_C_Jecon<2> 2:04:59
恩
c/c++_xiaoxiao(1) 2:05:23
靠,和你讲线程扯到这来了。。。
c/c++_xiaoxiao(1) 2:05:25
擦。。
Linux_C_Jecon<2> 2:05:35
没事
c/c++_xiaoxiao(1) 2:04:54
排查
Linux_C_Jecon<2> 2:04:59
恩
c/c++_xiaoxiao(1) 2:05:23
靠,和你讲线程扯到这来了。。。
c/c++_xiaoxiao(1) 2:05:25
擦。。
Linux_C_Jecon<2> 2:05:35
没事
Linux_C_Jecon<2> 2:05:39
这个才是我要的
c/c++_xiaoxiao(1) 2:06:05
所谓的搓代码也能拼业务,就是这个道理。。。
Linux_C_Jecon<2> 2:06:11
恩
c/c++_xiaoxiao(1) 2:06:16
部署是很恶心的一个东西。。。。
c/c++_xiaoxiao(1) 2:06:19
这个,你找宇航,哈哈
c/c++_xiaoxiao(1) 2:06:21
宇航最熟悉这个了。。
Linux_C_Jecon<2> 2:06:31
我们老总也会这块
Linux_C_Jecon<2> 2:06:40
linux和unix的运维
c/c++_xiaoxiao(1) 2:06:41
天天部署业务。根据业务不同,折腾机器。。
Linux_C_Jecon<2> 2:06:46
是
Linux_C_Jecon<2> 2:07:03
每天都看到他在办公室折腾
c/c++_xiaoxiao(1) 2:07:07
像我这种打杂的,是没办法。。。
Linux_C_Jecon<2> 2:07:29
刚好我这边的架构也要涉及到一点点
Linux_C_Jecon<2> 2:07:34
运维的
c/c++_xiaoxiao(1) 2:07:49
架构这玩意,说难听点,和代码完全不沾边。。
Linux_C_Jecon<2> 2:07:57
恩是的
c/c++_xiaoxiao(1) 2:08:00
说白了,架构就是在拆各个模块
Linux_C_Jecon<2> 2:08:03
看是什么架构了
c/c++_xiaoxiao(1) 2:08:02
设计好接口
Linux_C_Jecon<2> 2:08:08
恩
c/c++_xiaoxiao(1) 2:08:10
然后模块内部,有多大
c/c++_xiaoxiao(1) 2:08:14
太大,就继续拆
c/c++_xiaoxiao(1) 2:08:19
拆到够小了
c/c++_xiaoxiao(1) 2:08:22
代码再搓。。。
c/c++_xiaoxiao(1) 2:08:26
都能用。。
c/c++_xiaoxiao(1) 2:08:31
反正接口不变就好
Linux_C_Jecon<2> 2:08:37
恩
c/c++_xiaoxiao(1) 2:08:41
至于小模块内部如何设计,如何实现。。
c/c++_xiaoxiao(1) 2:08:44
随你了。。
c/c++_xiaoxiao(1) 2:08:52
反正,外部只调用你的接口。
Linux_C_Jecon<2> 2:08:59
恩
c/c++_xiaoxiao(1) 2:08:59
自己代码自己维护去。。
Linux_C_Jecon<2> 2:09:12
恩
c/c++_xiaoxiao(1) 2:09:21
说实话,架构这玩意,都烂透了。。
c/c++_xiaoxiao(1) 2:09:31
现在的那一堆的互联网产品,架构都在数据库上。。
Linux_C_Jecon<2> 2:09:42
是
c/c++_xiaoxiao(1) 2:09:46
至于其他的,网上各种文早就分干净了。。。
c/c++_xiaoxiao(1) 2:09:54
不同业务,对数据库压力不同,数据库搞定了,啥都搞定了。
Linux_C_Jecon<2> 2:10:03
恩
c/c++_xiaoxiao(1) 2:10:25
存储 IO 并发。。。
c/c++_xiaoxiao(1) 2:10:33
就这3了。
C:\Users\tiny>cat 1.cpp
class Base {
public:
static int a;
};
int Base::a = 1;
template <typename T>
class C {
public:
static void demo() {
T::a = 100;
}
};
int main()
{
C<Base>::demo();
return 0;
}
C:\Users\tiny>g++ 1.cpp
C:\Users\tiny>
c/c++_xiaoxiao(1) 0:53:49
没辙,这就是区别。。
Linux_C_Jecon<2> 0:54:04
不行。。。
Linux_C_Jecon<2> 0:54:08
NND 语法规定
Linux_C_Jecon<2> 0:54:28
c++不严谨哎
c/c++_xiaoxiao(1) 0:54:28
所以我说,写多了c++,容易为所欲为。。
c/c++_xiaoxiao(1) 0:54:35
很严谨啊
c/c++_xiaoxiao(1) 0:54:48
T确实有一个静态成员是a啊
c/c++_xiaoxiao(1) 0:54:54
既然有,那就可以访问啊
Linux_C_Jecon<2> 0:55:15
问题是java的入口类是静态的啊
c/c++_xiaoxiao(1) 0:55:26
这和静态动态无关啊
Linux_C_Jecon<2> 0:55:30
有啊
Linux_C_Jecon<2> 0:55:34
我发给你看嘛
c/c++_xiaoxiao(1) 0:55:41
主要是,java的泛型是运行时的
c/c++_xiaoxiao(1) 0:55:43
这个才是悲剧
Linux_C_Jecon<2> 0:56:02
class DBM<Type extends Base>{
public void demo(){
Type.a=100;
System.out.println("Type.a="+Type.a);
}
}
Linux_C_Jecon<2> 0:56:06
这个是动态的
Linux_C_Jecon<2> 0:56:22
Linux_C_Jecon<2> 0:56:27
改成静态的就报错
Linux_C_Jecon<2> 0:56:42
跟泛型无关啊
Linux_C_Jecon<2> 0:56:49
跟语法有关吧
c/c++_xiaoxiao(1) 0:56:53
核心在于,泛型本身是运行时确定的
c/c++_xiaoxiao(1) 0:57:00
static是静态的
Linux_C_Jecon<2> 0:57:08
是啊
c/c++_xiaoxiao(1) 0:57:10
没法获知泛型本身的类型了。
c/c++_xiaoxiao(1) 0:57:19
所以说...java弱啊。。。
Linux_C_Jecon<2> 0:57:20
Linux_C_Jecon<2> 0:57:25
看嘛 没办法嘛
c/c++_xiaoxiao(1) 0:57:25
泛型如果是编译时的话
c/c++_xiaoxiao(1) 0:57:27
就没这个问题了。
Linux_C_Jecon<2> 0:57:33
跟Type无关啊
Linux_C_Jecon<2> 0:57:43
不是编译时的问题
c/c++_xiaoxiao(1) 0:57:44
所以,要学c++啊,把泛型丢到编译时,一点问题都没了。
Linux_C_Jecon<2> 0:58:06
这个是直接写成你那样的。eclipse语法解析器就报错了
Linux_C_Jecon<2> 0:58:10
还没进入编译
c/c++_xiaoxiao(1) 0:58:24
...之所以不支持这个语法
Linux_C_Jecon<2> 0:58:27
这个是未编译的状态啊
Linux_C_Jecon<2> 0:58:28
恩恩
Linux_C_Jecon<2> 0:58:32
不支持这个语法
c/c++_xiaoxiao(1) 0:58:32
就是因为,泛型是运行时确定的啊
c/c++_xiaoxiao(1) 0:58:43
你想想啊
Linux_C_Jecon<2> 0:58:49
跟泛型无关啊啊
Linux_C_Jecon<2> 0:58:56
换别的写法也不行啊
c/c++_xiaoxiao(1) 0:59:00
因为,static是要在所有runtime加载前执行的
c/c++_xiaoxiao(1) 0:59:22
算了,我改天看看java的类加载器去,就明白了
c/c++_xiaoxiao(1) 0:59:25
为什么这个语法不让通过。
c/c++_xiaoxiao(1) 0:59:31
现在貌似很难解释。
Linux_C_Jecon<2> 1:00:29
Linux_C_Jecon<2> 1:00:39
不难解释啊
c/c++_xiaoxiao(1) 1:00:46
简单的说,static的时候,没有new出一个DBM的对象,那么他就不知道泛型是啥。
Linux_C_Jecon<2> 1:00:51
是
c/c++_xiaoxiao(1) 1:00:54
那么,他就无法判断出,这个泛型到底有啥成员
c/c++_xiaoxiao(1) 1:01:08
说白了,根本还在于,泛型必须运行时才能知道
c/c++_xiaoxiao(1) 1:01:18
c++之所以允许,是因为,泛型是处理是在编译时
Linux_C_Jecon<2> 1:01:22
简单的说,static的时候,没有new出一个DBM的对象,那么他就不让他传值
Linux_C_Jecon<2> 1:01:35
。。。。这个语法上明显不行嘛
c/c++_xiaoxiao(1) 1:01:39
因为,java的泛型是metadata
Linux_C_Jecon<2> 1:01:44
跟泛型没关系吧
c/c++_xiaoxiao(1) 1:01:50
额。
c/c++_xiaoxiao(1) 1:01:56
你这样理解也没错
Linux_C_Jecon<2> 1:02:08
是啊
Linux_C_Jecon<2> 1:02:22
确实是静态方法调不了动态方法啊
c/c++_xiaoxiao(1) 1:02:25
java的泛型是metadata
c/c++_xiaoxiao(1) 1:02:27
那么
Linux_C_Jecon<2> 1:02:34
不管换什么类型都一样啊
c/c++_xiaoxiao(1) 1:02:33
只有这个对象生成以后
Linux_C_Jecon<2> 1:02:38
恩
c/c++_xiaoxiao(1) 1:02:38
metadata才会初始化
c/c++_xiaoxiao(1) 1:02:39
你听我说完
c/c++_xiaoxiao(1) 1:02:49
那么,这个时候才知道,metadata里面这个类型,到底有啥成员
c/c++_xiaoxiao(1) 1:03:00
static的话,metadata压根没有被传递进去
c/c++_xiaoxiao(1) 1:03:07
所以,无法判断出,这个类型到底是啥
c/c++_xiaoxiao(1) 1:03:14
因为,java的类型,其实就在metadata里,对吧
c/c++_xiaoxiao(1) 1:03:25
你换这个角度理解,和泛型有关了么?
Linux_C_Jecon<2> 1:03:27
恩
c/c++_xiaoxiao(1) 1:03:35
通了吧
Linux_C_Jecon<2> 1:03:47
恩
c/c++_xiaoxiao(1) 1:03:48
c++的泛型,是编译期间,对每一行代码
c/c++_xiaoxiao(1) 1:03:52
都去做类型的匹配
Linux_C_Jecon<2> 1:03:53
你看的是哪本书啊
c/c++_xiaoxiao(1) 1:04:11
所以,c++的泛型,不依赖运行时的check,在编译的时候,比如我刚才给的代码
c/c++_xiaoxiao(1) 1:04:15
c<base>::demo()
Linux_C_Jecon<2> 1:04:16
哦
c/c++_xiaoxiao(1) 1:04:20
他首先回去看demo这个函数
c/c++_xiaoxiao(1) 1:04:24
demo里面,有T::a
c/c++_xiaoxiao(1) 1:04:29
然后,C的模板参数是Base
Linux_C_Jecon<2> 1:04:32
恩
c/c++_xiaoxiao(1) 1:04:39
T被实例化成Base类型
c/c++_xiaoxiao(1) 1:04:45
那么,他会去检查,Base有没有一个静态成员a
c/c++_xiaoxiao(1) 1:04:49
如果有,pass,没有报错
c/c++_xiaoxiao(1) 1:04:56
不需要到运行时去做check
Linux_C_Jecon<2> 1:05:12
你没看出什么问题吗
c/c++_xiaoxiao(1) 1:05:18
说白了,还是因为java的泛型实例化的时机和c++不同,导致了这个语法必定不能通过
Linux_臭臭<pylay.shen@gmail.com> 1:05:39
wing 在哪设置字符集呢
Linux_C_Jecon<2> 1:05:46
恩
Linux_C_Jecon<2> 1:05:48
是的
c/c++_xiaoxiao(1) 1:06:00
这样解释都通了吧?
c/c++_xiaoxiao(1) 1:06:05
没啥疑问了吧
c/c++_xiaoxiao(1) 1:06:23
书啊,看java虚拟机的相关资料吧
c/c++_xiaoxiao(1) 1:06:40
因为java的泛型本质是metadata,所以对于内置类型
Linux_C_Jecon<2> 1:06:46
C:\Users\tiny>cat 1.cpp
class Base {
public:
static int a;
};
int Base::a = 1;
template <typename T>
class C {
public:
static void demo() {
T::a = 100;
}
};
这句话在JAVA里面是明显过不去的
Linux_C_Jecon<2> 1:06:47
恩恩
c/c++_xiaoxiao(1) 1:06:47
int short float double这种
c/c++_xiaoxiao(1) 1:06:51
就不能实例化了
Linux_C_Jecon<2> 1:07:00
你的T是动态的吧
c/c++_xiaoxiao(1) 1:07:03
所以,你无法生成一个List<int>
Linux_C_Jecon<2> 1:07:06
是
c/c++_xiaoxiao(1) 1:07:16
没错吧,本质和泛型还是有关吧
Linux_C_Jecon<2> 1:07:22
恩
c/c++_xiaoxiao(1) 1:07:22
不过你是从语言本身的语法入手
Linux_C_Jecon<2> 1:07:31
是的
c/c++_xiaoxiao(1) 1:07:30
我是从语言为什么不能这样设计入手的
Linux_C_Jecon<2> 1:07:37
哦
c/c++_xiaoxiao(1) 1:07:37
臭臭,貌似不能
c/c++_xiaoxiao(1) 1:07:52
我记得wingware不能设置非utf-8字符集
c/c++_xiaoxiao(1) 1:08:01
c++那个其实是静态的
Linux_C_Jecon<2> 1:08:07
那好吧
Linux_臭臭<pylay.shen@gmail.com> 1:08:09
不能 我也没找到
c/c++_xiaoxiao(1) 1:08:10
java把泛型做到了metadata里的好处是
c/c++_xiaoxiao(1) 1:08:13
你可以反射处理
Linux_C_Jecon<2> 1:08:14
就出在这个问题上
Linux_C_Jecon<2> 1:08:17
恩恩
Linux_C_Jecon<2> 1:08:31
用反射 直接调用类,不进行实例化就OK了
c/c++_xiaoxiao(1) 1:08:32
你可以运行时,通过反射,对一个泛型实例化
c/c++_xiaoxiao(1) 1:08:36
但是,c++就不行了
c/c++_xiaoxiao(1) 1:08:41
一样的,本质差不多
Linux_C_Jecon<2> 1:08:46
c++没有反射吧
c/c++_xiaoxiao(1) 1:08:45
反正都是通过metadata
c/c++_xiaoxiao(1) 1:08:48
对吧
Linux_C_Jecon<2> 1:08:55
是的
c/c++_xiaoxiao(1) 1:08:57
c++的泛型是编译时确定的
c/c++_xiaoxiao(1) 1:09:04
那么就是说,运行时,你永远不知道他是啥。。。
Linux_C_Jecon<2> 1:09:05
xiaoxiao有什么好书推荐几本
c/c++_xiaoxiao(1) 1:09:09
你也就无法生成2个一样的类型了。
Linux_C_Jecon<2> 1:09:11
恩
c/c++_xiaoxiao(1) 1:09:44
一个是static的,一个是runtime的,其实都有好处,只是,有时候太弱了。。。
c/c++_xiaoxiao(1) 1:09:50
好书?深入理解java虚拟机。。。
c/c++_xiaoxiao(1) 1:09:51
看么。。
Linux_C_Jecon<2> 1:09:52
是啊
Linux_C_Jecon<2> 1:10:09
额,公司刚买回来
Linux_C_Jecon<2> 1:10:13
还没去看
c/c++_xiaoxiao(1) 1:10:22
clr via c#
Linux_C_Jecon<2> 1:10:42
有没有C++线程类的书籍推荐下
c/c++_xiaoxiao(1) 1:10:48
线程?
Linux_C_Jecon<2> 1:11:01
并发类的
c/c++_xiaoxiao(1) 1:11:02
多线程本质和c++无关吧
Linux_C_Jecon<2> 1:11:12
恩
Linux_C_Jecon<2> 1:11:18
api总有吧
c/c++_xiaoxiao(1) 1:11:29
你到底是要看设计
c/c++_xiaoxiao(1) 1:11:31
还是要看API...
Linux_C_Jecon<2> 1:11:45
设计
c/c++_xiaoxiao(1) 1:11:54
比如说,如何设计一个多线程
c/c++_xiaoxiao(1) 1:11:58
还是,多线程如何用。。
c/c++_xiaoxiao(1) 1:12:03
你现在卡在哪个环节
Linux_C_Jecon<2> 1:12:06
多线程如何用
Linux_C_Jecon<2> 1:12:17
堵塞什么的
c/c++_xiaoxiao(1) 1:12:17
win/linux/mac?
c/c++_xiaoxiao(1) 1:12:22
额。。
Linux_C_Jecon<2> 1:12:24
linux
c/c++_xiaoxiao(1) 1:12:24
那个啊。。。
Linux_C_Jecon<2> 1:12:27
ubuntu
Linux_C_Jecon<2> 1:12:28
恩
c/c++_xiaoxiao(1) 1:13:16
多处理器编程的艺术
我记得是用java做的demo?
Linux_C_Jecon<2> 1:13:36
3Q
Linux_C_Jecon<2> 1:13:48
Java的会
Linux_C_Jecon<2> 1:13:59
关键是有API NND
c/c++_xiaoxiao(1) 1:14:16
额。。
c/c++_xiaoxiao(1) 1:14:24
API无外乎是互斥 自旋 读写
c/c++_xiaoxiao(1) 1:14:36
一般来说,你只会看到2把锁 互斥 读写
c/c++_xiaoxiao(1) 1:14:41
然后c的线程API
c/c++_xiaoxiao(1) 1:14:43
一律是这样的
Linux_C_Jecon<2> 1:14:49
读者写者的做法吗
c/c++_xiaoxiao(1) 1:15:04
status fun(callback, arg)
c/c++_xiaoxiao(1) 1:15:21
这是一个线程启动函数
c/c++_xiaoxiao(1) 1:15:26
然后一个线程函数
c/c++_xiaoxiao(1) 1:15:27
是这样的
c/c++_xiaoxiao(1) 1:15:32
statuc thread(arg)
c/c++_xiaoxiao(1) 1:15:42
也就是说,他只接受一个参数,然后返回一个状态
c/c++_xiaoxiao(1) 1:15:45
。。。
c/c++_xiaoxiao(1) 1:15:48
和java没啥区别啊
c/c++_xiaoxiao(1) 1:15:58
嗯,api就是读写锁和互斥锁了
Linux_C_Jecon<2> 1:16:09
恩
Linux_C_Jecon<2> 1:16:15
哦
c/c++_xiaoxiao(1) 1:16:29
至于那些调整线程属性的参数
c/c++_xiaoxiao(1) 1:16:33
你一律可以无视。。。
c/c++_xiaoxiao(1) 1:16:41
你要坚信,OS的自动调整比你手工设置好
c/c++_xiaoxiao(1) 1:16:57
除非你的业务环境非常特殊,所以这类参数一律传NULL就是了
c/c++_xiaoxiao(1) 1:17:28
pthread_create(attr, callback, callback_arg, thread_id);
c/c++_xiaoxiao(1) 1:17:47
第一个参数设置线程属性,然后是线程启动函数,线程启动函数的参数,线程的id
c/c++_xiaoxiao(1) 1:17:55
几乎所有的系统,线程都是这几个参数
c/c++_xiaoxiao(1) 1:18:13
关键是,你得看他的callback的函数声明,必须严格和他一样否则,小心core。。
Linux_C_Jecon<2> 1:18:34
恩
Linux_C_Jecon<2> 1:18:43
哦
Linux_C_Jecon<2> 1:19:12
有这方面的Demo或者是书籍吗
c/c++_xiaoxiao(1) 1:19:14
主要是,ABI的不一致,可能导致堆栈不平衡
c/c++_xiaoxiao(1) 1:19:22
demo?
Linux_C_Jecon<2> 1:19:26
额,abi是什么
c/c++_xiaoxiao(1) 1:19:35
...
c/c++_xiaoxiao(1) 1:19:38
我写个例子吧
c/c++_xiaoxiao(1) 1:19:39
比如
c/c++_xiaoxiao(1) 1:19:44
void fun(int a, int b);
c/c++_xiaoxiao(1) 1:19:48
void bar(int a);
Linux_C_Jecon<2> 1:19:49
恩
c/c++_xiaoxiao(1) 1:20:04
当传函数指针的时候,为什么编译器会告诉你,函数不匹配
c/c++_xiaoxiao(1) 1:20:14
表面看起来,是声明不同
c/c++_xiaoxiao(1) 1:20:14
对吧
c/c++_xiaoxiao(1) 1:20:22
但是,函数,本质就是一个地址
c/c++_xiaoxiao(1) 1:20:23
对吧
c/c++_xiaoxiao(1) 1:20:34
声明不同反正都是一个地址,报错干啥
c/c++_xiaoxiao(1) 1:20:40
因为,ABI不一致
c/c++_xiaoxiao(1) 1:20:54
你看了2天android的那2B虚拟机的汇编了
c/c++_xiaoxiao(1) 1:20:58
大概知道点了吧
Linux_C_Jecon<2> 1:21:03
恩知道
c/c++_xiaoxiao(1) 1:21:13
比如,我用内存传参
c/c++_xiaoxiao(1) 1:21:28
本来,我接受的函数参数是2个
c/c++_xiaoxiao(1) 1:21:35
那么,我就会去内存里面,读2个值出来
c/c++_xiaoxiao(1) 1:21:38
对吧
c/c++_xiaoxiao(1) 1:21:45
你现在,给我的函数,其实只有一个参数
c/c++_xiaoxiao(1) 1:21:52
但是,对他来说,他是不知道的
c/c++_xiaoxiao(1) 1:21:58
所以,我依旧会读2个参数。
c/c++_xiaoxiao(1) 1:21:59
对不对?
c/c++_xiaoxiao(1) 1:22:05
第二个参数读到啥了。。。
Linux_C_Jecon<2> 1:22:12
恩
c/c++_xiaoxiao(1) 1:22:11
越界了。。
c/c++_xiaoxiao(1) 1:22:13
是吧。
Linux_C_Jecon<2> 1:22:26
是的
c/c++_xiaoxiao(1) 1:22:43
这种行为,可能导致崩溃吧
c/c++_xiaoxiao(1) 1:22:46
这个就叫做abi不一直
c/c++_xiaoxiao(1) 1:22:48
不一致
Linux_C_Jecon<2> 1:22:55
哦
c/c++_xiaoxiao(1) 1:23:06
再举个例子
c/c++_xiaoxiao(1) 1:23:09
我有4个寄存器
c/c++_xiaoxiao(1) 1:23:23
我和你约定,我的头4个参数,都用寄存器传参,依次用寄存器R1 R2 R3 R4
c/c++_xiaoxiao(1) 1:23:34
然后,你给我传参的时候,你实质上是这样传递的
c/c++_xiaoxiao(1) 1:23:40
4个参数依次用R4 R3 R2 R1...
c/c++_xiaoxiao(1) 1:23:46
那么,我读到的4个参数,变成啥了。。
Linux_C_Jecon<2> 1:23:59
认不到
c/c++_xiaoxiao(1) 1:24:16
但是,我压根不知道啊
Linux_C_Jecon<2> 1:24:23
是的
c/c++_xiaoxiao(1) 1:24:23
我以为,你传递的方式和我要求的一致
c/c++_xiaoxiao(1) 1:24:34
所以,解析的时候,就会解释出错误的值
Linux_C_Jecon<2> 1:24:40
恩
c/c++_xiaoxiao(1) 1:24:42
比如,第一个参数,本来是int,最后一个参数是一个pointer
c/c++_xiaoxiao(1) 1:24:56
你的本意是传一个0,传一个0xff
c/c++_xiaoxiao(1) 1:25:14
结果,我把0xff当作int了,解释成了255,把0当作指针了,解析成了NULL
c/c++_xiaoxiao(1) 1:25:17
那么,悲剧了吧
Linux_C_Jecon<2> 1:25:23
恩
c/c++_xiaoxiao(1) 1:25:31
这个也叫做ABI不一致
c/c++_xiaoxiao(1) 1:25:37
当然,ABI基本上是由编译器在维护的
Linux_C_Jecon<2> 1:25:38
差不多
c/c++_xiaoxiao(1) 1:25:49
但是,有声明的
c/c++_xiaoxiao(1) 1:25:53
比如你在windows下看到的
c/c++_xiaoxiao(1) 1:25:57
stdcall
c/c++_xiaoxiao(1) 1:25:58
cdecl
c/c++_xiaoxiao(1) 1:26:00
thiscall
c/c++_xiaoxiao(1) 1:26:06
这个就是ABI
Linux_C_Jecon<2> 1:26:10
哦
c/c++_xiaoxiao(1) 1:26:11
他们约束了,一个函数的参数如何传递
c/c++_xiaoxiao(1) 1:26:14
在linux下
c/c++_xiaoxiao(1) 1:26:23
有__attribute__(asmlinkage(....))
c/c++_xiaoxiao(1) 1:26:32
attribute里面的我忘记具体如何的了。
c/c++_xiaoxiao(1) 1:26:37
他也是约定传参规范的。
Linux_C_Jecon<2> 1:26:42
额
c/c++_xiaoxiao(1) 1:26:50
貌似是这样的
c/c++_xiaoxiao(1) 1:26:52
反正有个宏。。
Linux_C_Jecon<2> 1:26:55
这样啊,我倒是没去关注编译器的问题
Linux_C_Jecon<2> 1:27:04
恩
c/c++_xiaoxiao(1) 1:27:06
如果某个函数的一个参数
c/c++_xiaoxiao(1) 1:27:07
是一个callback
c/c++_xiaoxiao(1) 1:27:13
然后,他的声明里面有这些东西
c/c++_xiaoxiao(1) 1:27:19
你实现的函数,没有写这个。
c/c++_xiaoxiao(1) 1:27:28
那么,编译器就不会去生成那个特殊的调用约定
c/c++_xiaoxiao(1) 1:27:37
对于c代码来说,这是一个警告,对于c++来说,这是一个错误
c/c++_xiaoxiao(1) 1:27:44
如果,你无视这个,强转。。
Linux_C_Jecon<2> 1:27:47
恩
c/c++_xiaoxiao(1) 1:27:50
你说会有啥后果。。
c/c++_xiaoxiao(1) 1:28:29
这里还没扯到堆栈平衡。。。只是讲了ABI的传参部分,ABI还有一个部分是堆栈平衡
c/c++_xiaoxiao(1) 1:28:33
又谁来负责清理堆栈
c/c++_xiaoxiao(1) 1:28:59
比如,传参用内存传参的话
c/c++_xiaoxiao(1) 1:29:05
谁来销毁这些内存呢?
c/c++_xiaoxiao(1) 1:29:11
ABI的类型决定的
Linux_C_Jecon<2> 1:29:17
哦
c/c++_xiaoxiao(1) 1:29:31
因为,现在的编译器模型。。
c/c++_xiaoxiao(1) 1:29:36
返回地址是在这些内存上的。。
c/c++_xiaoxiao(1) 1:29:50
所以,如果ABI匹配出错了,那么函数的返回地址就会解析错
c/c++_xiaoxiao(1) 1:29:56
这个时候,就会出现core了。
c/c++_xiaoxiao(1) 1:30:05
或者是,函数的栈不知道飞哪里去了。
Linux_C_Jecon<2> 1:30:20
恩
c/c++_xiaoxiao(1) 1:30:21
当然,你还可以手工的让函数的返回地址解析出错。。
c/c++_xiaoxiao(1) 1:30:25
答案就是,数组越界。。。
c/c++_xiaoxiao(1) 1:30:34
直接覆盖掉那个函数的返回地址
c/c++_xiaoxiao(1) 1:30:51
和ABI不匹配不同,他是覆盖了返回地址,ABI不匹配是返回地址本身是对的,但是解析的时候,解析到其他位置去了
c/c++_xiaoxiao(1) 1:31:02
这个,一般出现在用汇编手写函数的时候
Linux_C_Jecon<2> 1:31:14
哦
c/c++_xiaoxiao(1) 1:31:19
因为,汇编手写函数的时候,很容易忘记清理函数栈。。
c/c++_xiaoxiao(1) 1:31:31
对于android上的应用
c/c++_xiaoxiao(1) 1:31:35
最容易出现问题的就是
c/c++_xiaoxiao(1) 1:31:39
你们以后做hook
Linux_C_Jecon<2> 1:31:48
恩
c/c++_xiaoxiao(1) 1:31:48
比如,你想拦截用户打电话
c/c++_xiaoxiao(1) 1:31:54
假如
c/c++_xiaoxiao(1) 1:31:59
你又找不到,系统提供了一个event给你
c/c++_xiaoxiao(1) 1:32:14
那么,你唯一的做法,就是劫持掉那个打电话的API
Linux_C_Jecon<2> 1:32:24
恩
c/c++_xiaoxiao(1) 1:32:26
但是,你又不能改系统代码。。。
c/c++_xiaoxiao(1) 1:32:32
因为,你的app要通用。。
c/c++_xiaoxiao(1) 1:32:41
否则,只能自家的ROM上跑
c/c++_xiaoxiao(1) 1:32:48
所以,你得改机器码。。。
c/c++_xiaoxiao(1) 1:33:01
这个时候,就得汇编写那么一小块的跳转代码了。
c/c++_xiaoxiao(1) 1:33:12
那个时候,就需要那种恶心问题了
Linux_C_Jecon<2> 1:33:17
恩
Linux_C_Jecon<2> 1:33:35
哪种恶心的问题
Linux_C_Jecon<2> 1:33:38
汇编吗
c/c++_xiaoxiao(1) 1:33:40
所以,线程的启动函数,你保证,参数类型一致就够了。
Linux_C_Jecon<2> 1:33:44
写汇编吗
c/c++_xiaoxiao(1) 1:33:44
嗯。。
c/c++_xiaoxiao(1) 1:33:48
嗯。。
Linux_C_Jecon<2> 1:33:52
恩
c/c++_xiaoxiao(1) 1:34:06
其他,没啥了。
c/c++_xiaoxiao(1) 1:34:13
其他就是所谓的加mutex了。。
Linux_C_Jecon<2> 1:34:18
哦
c/c++_xiaoxiao(1) 1:34:18
记得上各种mutex就好了
Linux_C_Jecon<2> 1:34:23
这个倒是学过
Linux_C_Jecon<2> 1:34:38
如果要处理非堵塞的问题,怎么做
c/c++_xiaoxiao(1) 1:34:45
非阻塞?
c/c++_xiaoxiao(1) 1:34:46
具体
c/c++_xiaoxiao(1) 1:35:00
来个场景
Linux_C_Jecon<2> 1:35:04
肯定是会有堵塞,非堵塞中肯定是会有堵塞的 类似JAVA 的NIO
c/c++_xiaoxiao(1) 1:35:11
你是说IO么?
Linux_C_Jecon<2> 1:35:15
恩
c/c++_xiaoxiao(1) 1:35:16
还是说线程本身
Linux_C_Jecon<2> 1:35:21
线程
c/c++_xiaoxiao(1) 1:35:27
线程本身就是非阻塞的啊,除非你上mutex,否则一定异步
Linux_C_Jecon<2> 1:35:30
多个线程共享一个临界区
c/c++_xiaoxiao(1) 1:35:37
那就上mutex呗。。
c/c++_xiaoxiao(1) 1:35:44
进临界区加mutex,出来干掉mutex
Linux_C_Jecon<2> 1:36:06
那如果线程在临界区卡住了呢
Linux_C_Jecon<2> 1:36:18
也就是堵住了临界区的入口出不去了
c/c++_xiaoxiao(1) 1:36:18
...这种问题
c/c++_xiaoxiao(1) 1:36:25
怎么会呢?
c/c++_xiaoxiao(1) 1:36:28
除非你在里面死循环了。
Linux_C_Jecon<2> 1:36:32
比如发送异常的情况
c/c++_xiaoxiao(1) 1:36:35
或者死锁了。
c/c++_xiaoxiao(1) 1:36:40
异常么?
Linux_C_Jecon<2> 1:36:45
对 就是说死锁
Linux_C_Jecon<2> 1:36:46
恩恩
Linux_C_Jecon<2> 1:36:47
是的
c/c++_xiaoxiao(1) 1:36:48
异常你catch了,他会自动帮你释放掉的。
c/c++_xiaoxiao(1) 1:36:55
死锁的话,那个是设计问题了。
Linux_C_Jecon<2> 1:37:01
哦
c/c++_xiaoxiao(1) 1:37:21
准确点说,是catch了以后,你得记得释放临界区。。
Linux_C_Jecon<2> 1:37:27
恩
Linux_C_Jecon<2> 1:37:36
让线程进入等待
c/c++_xiaoxiao(1) 1:37:35
所以,你在临界区里面抛异常的时候,一定记得提示额外信息。。
Linux_C_Jecon<2> 1:37:46
恩
c/c++_xiaoxiao(1) 1:37:46
其实,最好是临界区的里面别抛异常。。
c/c++_xiaoxiao(1) 1:37:57
本身,临界区就应该尽量避免复杂化
c/c++_xiaoxiao(1) 1:38:03
里面抛异常,里面接。。
Linux_C_Jecon<2> 1:38:04
这个倒是很难保证啊
c/c++_xiaoxiao(1) 1:38:08
这是基本的原则
Linux_C_Jecon<2> 1:38:14
额
c/c++_xiaoxiao(1) 1:38:19
那就里面抛,里面接,不要让异常从临界区跑出来
Linux_C_Jecon<2> 1:38:26
恩
c/c++_xiaoxiao(1) 1:38:39
一般来说
c/c++_xiaoxiao(1) 1:38:48
非系统资源导致的异常
c/c++_xiaoxiao(1) 1:38:58
很难在临界区抛出来吧。。代码bug除外
Linux_C_Jecon<2> 1:39:06
是的
c/c++_xiaoxiao(1) 1:39:06
代码bug那个可以改,测试的时候就应该能发现。
Linux_C_Jecon<2> 1:39:14
除非把异常往外抛了
c/c++_xiaoxiao(1) 1:39:15
系统异常了,我觉得。。。
c/c++_xiaoxiao(1) 1:39:31
app就算多活那么一会,过会也得死。。
c/c++_xiaoxiao(1) 1:39:32
没错吧。。
Linux_C_Jecon<2> 1:39:39
是
c/c++_xiaoxiao(1) 1:39:44
就好比,你在java里面
Linux_C_Jecon<2> 1:39:46
直接死机了
c/c++_xiaoxiao(1) 1:39:48
new失败了。。
c/c++_xiaoxiao(1) 1:39:56
这个异常,你接过来,其实,你真的做不了啥了。
c/c++_xiaoxiao(1) 1:40:01
没错吧。。。
Linux_C_Jecon<2> 1:40:04
是
c/c++_xiaoxiao(1) 1:40:16
所以,你关注几个重点异常就好了
c/c++_xiaoxiao(1) 1:40:18
1. socket
c/c++_xiaoxiao(1) 1:40:21
2. 文件io
c/c++_xiaoxiao(1) 1:40:37
文件io异常,要么是没权限,要么是目录不存在,要么是磁盘满了。。
Linux_C_Jecon<2> 1:40:45
恩
c/c++_xiaoxiao(1) 1:40:45
我觉得,这几个情况,编码上就能干掉吧。。
c/c++_xiaoxiao(1) 1:40:52
check一把就好了
Linux_C_Jecon<2> 1:41:00
恩
c/c++_xiaoxiao(1) 1:41:05
至于socket,自己抓个异常,看看socket状态,也出来了吧
Linux_C_Jecon<2> 1:41:16
恩
c/c++_xiaoxiao(1) 1:41:28
那么,系统资源异常,也基本能干掉了,说白了,最后的问题就是你那把锁,设计得多复杂了。。
Linux_C_Jecon<2> 1:41:30
我想用C写个多线程的
Linux_C_Jecon<2> 1:41:35
恩
Linux_C_Jecon<2> 1:41:42
问你个问题
Linux_C_Jecon<2> 1:41:48
C有线程池吗
c/c++_xiaoxiao(1) 1:41:57
没有。。
c/c++_xiaoxiao(1) 1:41:58
自己实现。。
Linux_C_Jecon<2> 1:42:15
额
Linux_C_Jecon<2> 1:42:16
好吧
c/c++_xiaoxiao(1) 1:42:19
其实锁的问题比你想象中简单的多。。
c/c++_xiaoxiao(1) 1:42:29
因为,绝大部分的锁,可以被封装掉
Linux_C_Jecon<2> 1:42:37
恩
c/c++_xiaoxiao(1) 1:42:52
当然,代价就是性能下降了,因为每次调用,他里面必然有加锁解锁
c/c++_xiaoxiao(1) 1:43:00
线程池这个玩意。。。
c/c++_xiaoxiao(1) 1:43:05
比你想的作用要小
c/c++_xiaoxiao(1) 1:43:22
线程池无外乎就是,开一堆的线程,要用的时候丢个任务进去,然后88
Linux_C_Jecon<2> 1:43:27
恩是的
c/c++_xiaoxiao(1) 1:43:34
说实话,开个线程的开销其实不大。。
Linux_C_Jecon<2> 1:43:49
线程池主要是管理线程
c/c++_xiaoxiao(1) 1:43:49
然后,丢个任务进去,他啥时候做你还不知道,对吧
Linux_C_Jecon<2> 1:44:05
看怎么设计了
c/c++_xiaoxiao(1) 1:44:07
线程池的根本目的是,减少线程开销
Linux_C_Jecon<2> 1:44:13
是
c/c++_xiaoxiao(1) 1:44:23
线程的开销,其实不大。。
c/c++_xiaoxiao(1) 1:44:24
真不大。。。
Linux_C_Jecon<2> 1:44:29
当有空闲的线程,通过线程池调用
c/c++_xiaoxiao(1) 1:44:28
你想得太复杂了
c/c++_xiaoxiao(1) 1:44:41
你不去做服务端上的高并发,很难遇上需要线程池
Linux_C_Jecon<2> 1:44:43
你一般不用线程池吗
c/c++_xiaoxiao(1) 1:44:48
但是,服务端的高并发。。。
c/c++_xiaoxiao(1) 1:44:54
一般线程创建了,就闲不下来了。。
Linux_C_Jecon<2> 1:45:00
是的
c/c++_xiaoxiao(1) 1:45:03
所以,压根不会出现空闲线程,需要管理的情况
c/c++_xiaoxiao(1) 1:45:20
其实线程池的根本目的,无外乎是怕你有个任务,很快完成了,然后做完,线程88了
c/c++_xiaoxiao(1) 1:45:28
你保证,他无限制的接任务就好了。。。
Linux_C_Jecon<2> 1:45:53
恩 对的
c/c++_xiaoxiao(1) 1:45:55
除非你去写一个基础库,提供给别人用
c/c++_xiaoxiao(1) 1:46:00
否则,线程池这种很复杂的东西
c/c++_xiaoxiao(1) 1:46:03
你完全看屏蔽掉
c/c++_xiaoxiao(1) 1:46:07
因为,你知道自己的业务是啥
c/c++_xiaoxiao(1) 1:46:12
你完全可以一个for循环接任务。。。
c/c++_xiaoxiao(1) 1:46:14
接到死。。
Linux_C_Jecon<2> 1:46:16
恩
c/c++_xiaoxiao(1) 1:46:29
线程池的问题是,他是一个基础库,他没法知道具体的业务。。
c/c++_xiaoxiao(1) 1:46:35
所以才会抽象级别那么高。。
c/c++_xiaoxiao(1) 1:47:05
对于频繁的短任务,其实真的设计里面,很少会出现,大量频繁的需要异步调用的短任务吧。。。
Linux_C_Jecon<2> 1:47:06
恩 他只要管理好线程就行了,比如某个线程做完事 继续等待
c/c++_xiaoxiao(1) 1:47:13
其实,同步调用完全够用了吧
Linux_C_Jecon<2> 1:47:17
是的
c/c++_xiaoxiao(1) 1:47:19
你不会,是个函数你就想异步调用下吧
c/c++_xiaoxiao(1) 1:47:26
绝大部分的逻辑,你可以在当前线程做了吧
c/c++_xiaoxiao(1) 1:47:35
耗时的,无外乎是IO(网络,本地)
c/c++_xiaoxiao(1) 1:47:39
大不了走异步io就是了
Linux_C_Jecon<2> 1:47:45
哦
c/c++_xiaoxiao(1) 1:47:53
然后callback处理回调完成的事件,和信号一样
Linux_C_Jecon<2> 1:48:00
恩
c/c++_xiaoxiao(1) 1:48:04
他自动在完成的时候,调用你传进去的callback
c/c++_xiaoxiao(1) 1:48:20
所以说,线程池那个东西,本身不是刚需。。
c/c++_xiaoxiao(1) 1:48:27
就看你如何设计自己的代码了。
c/c++_xiaoxiao(1) 1:48:34
当然,去写个线程池也挺好的。
Linux_C_Jecon<2> 1:49:00
如果我写个游戏服务器的话,是会遇到线程池的问题
Linux_C_Jecon<2> 1:49:01
恩
c/c++_xiaoxiao(1) 1:49:10
不用啊。。
Linux_C_Jecon<2> 1:49:15
为啥啊
linux_电工(79127502) 1:49:18
起床尿尿了
Linux_C_Jecon<2> 1:49:20
我写私服
c/c++_xiaoxiao(1) 1:49:27
你觉得线程池放在哪里部分。。
c/c++_xiaoxiao(1) 1:49:31
网络并发?
Linux_C_Jecon<2> 1:49:35
是
c/c++_xiaoxiao(1) 1:49:39
还是各种事件处理?
c/c++_xiaoxiao(1) 1:49:44
事件处理可以同步掉吧。。
Linux_C_Jecon<2> 1:49:48
并发
2013-04-24
c/c++_xiaoxiao(1) 1:49:56
并发,那个为什么要线程池?
Linux_C_Jecon<2> 1:50:10
恩 处理不同的事件啊
c/c++_xiaoxiao(1) 1:50:11
我开1个线程,死循环在哪里接socket事件就好了
Linux_C_Jecon<2> 1:50:17
哦
c/c++_xiaoxiao(1) 1:50:18
接到以后,dispatch给不同的线程
c/c++_xiaoxiao(1) 1:50:30
A线程,专门处理用户移动
c/c++_xiaoxiao(1) 1:50:39
B线程,专门处理用户释放技能
c/c++_xiaoxiao(1) 1:50:40
...
Linux_C_Jecon<2> 1:50:53
恩
c/c++_xiaoxiao(1) 1:51:07
接到socket事件,把socket包丢给dispatch线程,dispatch线程简单解包,看事件类型,丢给ABCD.
Linux_C_Jecon<2> 1:51:21
如果是1000人在线要怎么处理
Linux_C_Jecon<2> 1:51:39
你的意思是说消息队列吗
c/c++_xiaoxiao(1) 1:51:39
你觉得dispatch太慢的话,dispatch按照包的id,id % 3 == 1 id % 3 ==0 id %3 == 2丢给1 2 3这3个线程
c/c++_xiaoxiao(1) 1:51:47
这3个线程,再丢给下面的线程去处理
c/c++_xiaoxiao(1) 1:51:52
不用啊,一路dispatch就好了啊
Linux_C_Jecon<2> 1:51:54
哦
c/c++_xiaoxiao(1) 1:51:58
一个生产者,多个消费者啊
Linux_C_Jecon<2> 1:52:03
哦哦
c/c++_xiaoxiao(1) 1:52:05
你觉得,这种模式还太慢的话
c/c++_xiaoxiao(1) 1:52:14
消费者再分层
c/c++_xiaoxiao(1) 1:52:16
没问题吧
Linux_C_Jecon<2> 1:52:26
明白了
c/c++_xiaoxiao(1) 1:52:31
消费者在当前自己这一环节,他又是一个生产者的身份
linux_电工(79127502) 1:52:31
Linux_C_Jecon<2> 1:52:37
生产者是主线程把控的
c/c++_xiaoxiao(1) 1:52:37
继续往下dispatch
c/c++_xiaoxiao(1) 1:52:42
嗯
linux_电工(79127502) 1:52:42
你们两不打算睡觉了吗
c/c++_xiaoxiao(1) 1:52:49
第一个生产者,处理socket事件就好了
Linux_C_Jecon<2> 1:52:56
恩
c/c++_xiaoxiao(1) 1:53:02
他只接socket实践,不对socket事件做任何处理
c/c++_xiaoxiao(1) 1:53:06
抓到了,往下丢
c/c++_xiaoxiao(1) 1:53:09
收包啥的,其他人去做
Linux_C_Jecon<2> 1:53:13
恩
c/c++_xiaoxiao(1) 1:53:23
然后,初步解包,按照包里面的事件不同
c/c++_xiaoxiao(1) 1:53:27
丢给不同的thread去做处理
c/c++_xiaoxiao(1) 1:53:33
需要线程池么?
Linux_C_Jecon<2> 1:53:35
再分发
c/c++_xiaoxiao(1) 1:53:39
嗯
c/c++_xiaoxiao(1) 1:53:41
需要线程池么。。
c/c++_xiaoxiao(1) 1:53:45
一个生产者消费者搞定了。。
c/c++_xiaoxiao(1) 1:53:52
你觉得太慢就继续拆生产者消费模型
c/c++_xiaoxiao(1) 1:53:56
把类型细分。。
Linux_C_Jecon<2> 1:54:01
线程池的作用跟主线程的作用有点像
c/c++_xiaoxiao(1) 1:54:11
细分还不够,同一个类型的事件,就继续拆分
c/c++_xiaoxiao(1) 1:54:14
按照事件ID拆分
Linux_C_Jecon<2> 1:54:18
嗯呢
c/c++_xiaoxiao(1) 1:54:24
事件是3的倍数的,给线程3
c/c++_xiaoxiao(1) 1:54:29
2的倍数的,给线程2
c/c++_xiaoxiao(1) 1:54:31
其他的,给线程1
c/c++_xiaoxiao(1) 1:54:32
可以吧
c/c++_xiaoxiao(1) 1:54:41
再不行,加机器吧。。。。
c/c++_xiaoxiao(1) 1:54:50
需要线程池么。。
Linux_C_Jecon<2> 1:54:51
恩
c/c++_xiaoxiao(1) 1:54:55
我前面说过了
Linux_C_Jecon<2> 1:54:56
不需要
Linux_C_Jecon<2> 1:55:01
直接用缓存存储
c/c++_xiaoxiao(1) 1:55:02
线程池本身是作为一个高抽象的东西
c/c++_xiaoxiao(1) 1:55:08
他不知道你的业务具体的类型
c/c++_xiaoxiao(1) 1:55:19
导致,他必须支持通用的任务
每个业务每个缓存区
c/c++_xiaoxiao(1) 1:55:25
所以才会有那么个管理方式
Linux_C_Jecon<2> 1:55:32
恩
c/c++_xiaoxiao(1) 1:55:33
当你的业务本身是已知的时候
c/c++_xiaoxiao(1) 1:55:37
你完全没必要用线程池
c/c++_xiaoxiao(1) 1:55:42
自己对线程进行封装
c/c++_xiaoxiao(1) 1:55:45
该做啥做啥就好了
Linux_C_Jecon<2> 1:55:49
恩
c/c++_xiaoxiao(1) 1:56:05
当然,可能不如线程池经济,但是,简单的设计,好处就是容易排查问题
c/c++_xiaoxiao(1) 1:56:09
线程池的话,某个业务出问题了
c/c++_xiaoxiao(1) 1:56:13
你都不知道这个业务跑在哪里!
c/c++_xiaoxiao(1) 1:56:18
你知道么。。
Linux_C_Jecon<2> 1:56:22
不知道
c/c++_xiaoxiao(1) 1:56:23
排查恶心吧
Linux_C_Jecon<2> 1:56:37
经常发生这种问题
c/c++_xiaoxiao(1) 1:56:54
通用必然带来高抽象,那么带来的副作用就是排查问题复杂度增加
Linux_C_Jecon<2> 1:57:03
我们JAVA用的是XMPP服务下OPENFIRE框架,抱异常的时候,排查很痛苦
Linux_C_Jecon<2> 1:57:16
是的
c/c++_xiaoxiao(1) 1:57:23
所以,你看很多现在的框架
c/c++_xiaoxiao(1) 1:57:24
和项目
c/c++_xiaoxiao(1) 1:57:27
都提倡轻量级
c/c++_xiaoxiao(1) 1:57:32
他只提供一个分发接口
c/c++_xiaoxiao(1) 1:57:34
下面的东西
c/c++_xiaoxiao(1) 1:57:35
都自己做
c/c++_xiaoxiao(1) 1:57:36
对吧
Linux_C_Jecon<2> 1:57:45
对的
c/c++_xiaoxiao(1) 1:57:47
就是因为,具体的业务,自己最熟悉,自己好设计。
c/c++_xiaoxiao(1) 1:57:51
小心设计过度。。。
Linux_C_Jecon<2> 1:58:04
我很早以前用的是。。触发器
c/c++_xiaoxiao(1) 1:58:06
不过,作为线程池这种东西,咋说呢,自己去设计一个,也未必是坏事
Linux_C_Jecon<2> 1:58:09
观察者模式
Linux_C_Jecon<2> 1:58:11
恩
c/c++_xiaoxiao(1) 1:58:23
你设计的越加复杂,越加坑。
c/c++_xiaoxiao(1) 1:58:26
对于小规模的代码
c/c++_xiaoxiao(1) 1:58:36
大规模的代码,设计模式是有必要的,因为,思路可以清晰化,小规模的代码。。
c/c++_xiaoxiao(1) 1:58:44
设计模式,除了增加复杂性,我真不知道还能干啥。。。
Linux_C_Jecon<2> 1:58:54
也不是小规模的代码
c/c++_xiaoxiao(1) 1:58:57
就好比,我就一个cpp,200行,我有个全局变量,都不对外暴露
Linux_C_Jecon<2> 1:59:01
预计挺大的
c/c++_xiaoxiao(1) 1:59:03
我写个单例,有意义么。。
c/c++_xiaoxiao(1) 1:59:13
嗯,我只是说这个事而已
Linux_C_Jecon<2> 1:59:23
要是能承受的住10W的话,不用线程池好像不好管理
Linux_C_Jecon<2> 1:59:28
恩
c/c++_xiaoxiao(1) 1:59:34
10W并发,一般不考虑一台机器了。。。
Linux_C_Jecon<2> 1:59:41
额
c/c++_xiaoxiao(1) 1:59:46
榨干机器性能
c/c++_xiaoxiao(1) 1:59:57
不一定要这样选择
Linux_C_Jecon<2> 2:00:01
哦
c/c++_xiaoxiao(1) 2:00:01
简单点说
c/c++_xiaoxiao(1) 2:00:04
如果你一个业务
Linux_C_Jecon<2> 2:00:07
看集群了
c/c++_xiaoxiao(1) 2:00:06
你有10W的并发了
c/c++_xiaoxiao(1) 2:00:09
我不信
c/c++_xiaoxiao(1) 2:00:10
一台机器
c/c++_xiaoxiao(1) 2:00:12
你能跑完所有业务
Linux_C_Jecon<2> 2:00:24
看硬件的问题了
c/c++_xiaoxiao(1) 2:00:28
就算你能跑完。。你这台机器上的业务部署,得多复杂。。。
Linux_C_Jecon<2> 2:00:35
是的
c/c++_xiaoxiao(1) 2:00:41
你能拆么。。
Linux_C_Jecon<2> 2:00:48
拆不了
拆到N台机器上去。。。
Linux_C_Jecon<2> 2:00:54
可以试试
c/c++_xiaoxiao(1) 2:00:56
那真是设计问题了。。
c/c++_xiaoxiao(1) 2:01:01
一台机器撑10W并发。。。
c/c++_xiaoxiao(1) 2:01:08
这个概念。。。。
Linux_C_Jecon<2> 2:01:11
是说同样的模块拆分吗
c/c++_xiaoxiao(1) 2:01:16
我真的只能说,NB..
Linux_C_Jecon<2> 2:01:21
那倒是可以
c/c++_xiaoxiao(1) 2:01:22
简单点说
c/c++_xiaoxiao(1) 2:01:28
当你真的有10W并发的时候
Linux_C_Jecon<2> 2:01:33
我再做个代理
c/c++_xiaoxiao(1) 2:01:32
你的业务绝对不是简单的
Linux_C_Jecon<2> 2:01:37
恩
c/c++_xiaoxiao(1) 2:01:37
你肯定有很多复杂的功能
c/c++_xiaoxiao(1) 2:01:44
你一台机器,绝对跑不完
c/c++_xiaoxiao(1) 2:01:48
那么,你这个时候,要考虑的是
c/c++_xiaoxiao(1) 2:01:53
如何把业务分摊到不同的机器上去
Linux_C_Jecon<2> 2:01:57
哦
c/c++_xiaoxiao(1) 2:02:05
不要求每台机器都是全能的
Linux_C_Jecon<2> 2:02:08
这样啊
c/c++_xiaoxiao(1) 2:02:15
要求,每台机器专精一项或者是一个环节的业务
Linux_C_Jecon<2> 2:02:17
类似微信的做法吗
Linux_C_Jecon<2> 2:02:23
恩
c/c++_xiaoxiao(1) 2:02:27
然后,多台机器组成流水线
c/c++_xiaoxiao(1) 2:02:31
拼出一个完整业务
c/c++_xiaoxiao(1) 2:02:36
当然,如果你业务真的非常简单
Linux_C_Jecon<2> 2:02:37
哦
c/c++_xiaoxiao(1) 2:02:41
一台机器可以跑完,但是要求高并发
c/c++_xiaoxiao(1) 2:02:44
你的设计应该是
c/c++_xiaoxiao(1) 2:02:55
再做一个生产者,消费者
c/c++_xiaoxiao(1) 2:03:04
这个生产者叫做网关
c/c++_xiaoxiao(1) 2:03:13
他去做dispatch,给下面的机器,每台机器复杂一部分的业务
Linux_C_Jecon<2> 2:03:17
分发数据包到消费者手里
Linux_C_Jecon<2> 2:03:19
类似代理吗
c/c++_xiaoxiao(1) 2:03:23
嗯。
c/c++_xiaoxiao(1) 2:03:27
这个叫做网关。。。。
Linux_C_Jecon<2> 2:03:29
ngnix的做法
Linux_C_Jecon<2> 2:03:30
恩
Linux_C_Jecon<2> 2:03:34
负载均衡
c/c++_xiaoxiao(1) 2:03:41
看你的业务模型了
Linux_C_Jecon<2> 2:03:46
哦
c/c++_xiaoxiao(1) 2:03:45
不要想着全能
c/c++_xiaoxiao(1) 2:03:49
同样
c/c++_xiaoxiao(1) 2:03:51
你要榨干机器。。
c/c++_xiaoxiao(1) 2:03:59
某项业务不吃cpu,吃网络
c/c++_xiaoxiao(1) 2:04:08
某项业务不吃网络,吃cpu
c/c++_xiaoxiao(1) 2:04:16
如果你拆分的好,你完全可以。。。
c/c++_xiaoxiao(1) 2:04:18
懂我意思吧
Linux_C_Jecon<2> 2:04:27
恩
c/c++_xiaoxiao(1) 2:04:27
某些机器,部署A B业务,某些机器部署C业务
Linux_C_Jecon<2> 2:04:29
懂了
c/c++_xiaoxiao(1) 2:04:33
一样可以榨干系统性能
c/c++_xiaoxiao(1) 2:04:40
何必一台机器跑完ABCD...呢
c/c++_xiaoxiao(1) 2:04:43
徒增设计复杂性。。。
c/c++_xiaoxiao(1) 2:04:51
还有调试。。。
c/c++_xiaoxiao(1) 2:04:54
排查
Linux_C_Jecon<2> 2:04:59
恩
c/c++_xiaoxiao(1) 2:05:23
靠,和你讲线程扯到这来了。。。
c/c++_xiaoxiao(1) 2:05:25
擦。。
Linux_C_Jecon<2> 2:05:35
没事
c/c++_xiaoxiao(1) 2:04:54
排查
Linux_C_Jecon<2> 2:04:59
恩
c/c++_xiaoxiao(1) 2:05:23
靠,和你讲线程扯到这来了。。。
c/c++_xiaoxiao(1) 2:05:25
擦。。
Linux_C_Jecon<2> 2:05:35
没事
Linux_C_Jecon<2> 2:05:39
这个才是我要的
c/c++_xiaoxiao(1) 2:06:05
所谓的搓代码也能拼业务,就是这个道理。。。
Linux_C_Jecon<2> 2:06:11
恩
c/c++_xiaoxiao(1) 2:06:16
部署是很恶心的一个东西。。。。
c/c++_xiaoxiao(1) 2:06:19
这个,你找宇航,哈哈
c/c++_xiaoxiao(1) 2:06:21
宇航最熟悉这个了。。
Linux_C_Jecon<2> 2:06:31
我们老总也会这块
Linux_C_Jecon<2> 2:06:40
linux和unix的运维
c/c++_xiaoxiao(1) 2:06:41
天天部署业务。根据业务不同,折腾机器。。
Linux_C_Jecon<2> 2:06:46
是
Linux_C_Jecon<2> 2:07:03
每天都看到他在办公室折腾
c/c++_xiaoxiao(1) 2:07:07
像我这种打杂的,是没办法。。。
Linux_C_Jecon<2> 2:07:29
刚好我这边的架构也要涉及到一点点
Linux_C_Jecon<2> 2:07:34
运维的
c/c++_xiaoxiao(1) 2:07:49
架构这玩意,说难听点,和代码完全不沾边。。
Linux_C_Jecon<2> 2:07:57
恩是的
c/c++_xiaoxiao(1) 2:08:00
说白了,架构就是在拆各个模块
Linux_C_Jecon<2> 2:08:03
看是什么架构了
c/c++_xiaoxiao(1) 2:08:02
设计好接口
Linux_C_Jecon<2> 2:08:08
恩
c/c++_xiaoxiao(1) 2:08:10
然后模块内部,有多大
c/c++_xiaoxiao(1) 2:08:14
太大,就继续拆
c/c++_xiaoxiao(1) 2:08:19
拆到够小了
c/c++_xiaoxiao(1) 2:08:22
代码再搓。。。
c/c++_xiaoxiao(1) 2:08:26
都能用。。
c/c++_xiaoxiao(1) 2:08:31
反正接口不变就好
Linux_C_Jecon<2> 2:08:37
恩
c/c++_xiaoxiao(1) 2:08:41
至于小模块内部如何设计,如何实现。。
c/c++_xiaoxiao(1) 2:08:44
随你了。。
c/c++_xiaoxiao(1) 2:08:52
反正,外部只调用你的接口。
Linux_C_Jecon<2> 2:08:59
恩
c/c++_xiaoxiao(1) 2:08:59
自己代码自己维护去。。
Linux_C_Jecon<2> 2:09:12
恩
c/c++_xiaoxiao(1) 2:09:21
说实话,架构这玩意,都烂透了。。
c/c++_xiaoxiao(1) 2:09:31
现在的那一堆的互联网产品,架构都在数据库上。。
Linux_C_Jecon<2> 2:09:42
是
c/c++_xiaoxiao(1) 2:09:46
至于其他的,网上各种文早就分干净了。。。
c/c++_xiaoxiao(1) 2:09:54
不同业务,对数据库压力不同,数据库搞定了,啥都搞定了。
Linux_C_Jecon<2> 2:10:03
恩
c/c++_xiaoxiao(1) 2:10:25
存储 IO 并发。。。
c/c++_xiaoxiao(1) 2:10:33
就这3了。
相关文章推荐
- C++代码设计:向Java借鉴Builder模式塈OpenCL内核代码编译
- C++命令行模式编译设置
- 【面试题二】java实现的单例模式,c++实现单例模式,实现禁止拷贝
- 【面试题002】java实现的单例模式,c++实现单例模式,实现禁止拷贝
- 使用自动生成java文件和自动编译的动态代理模式-马士兵设计模式教程
- C++编译模式
- Ubuntu下学习编译运行 C/C++/Java
- C++ 模板编译模式
- eclipse编译调试java与ndk c++的混合代码
- 设计模式:策略模式的实现 c++ 与 java
- Eclipse C/C++/JAVA编译环境配置
- 为什么设计模式java实现的书比较多,C++却很少.
- C++ 单例模式中处理在类中声明一个指向一个自己的指针,在编译时显示定义的指针未定义的处理办法
- MFC之工厂模式(C++ & java)
- 非托管环境语言(c,c++)和托管环境语言(c#,java)的编译过程差别
- java编译过程与c/c++编译过程不同
- 编译哈工大语言技术平台云LTP(C++)源码及LTP4J(Java)源码
- 数据挖掘-关联分析频繁模式挖掘Apriori、FP-Growth及Eclat算法的JAVA及C++实现
- Java, C++ 单例模式与静态成员初始化对比
- hao—C++和Java从编译到运行的过程区别