Also, you want to distinguish between "self updating" and "running a bootloader."
Arduino, for example, usually utilizes a bootloader, which is an "extra small" piece of program memory with the ability to update the larger "application" part of program memory. With a bootloader, you only have to have "application_size + bootloader_size" worth of memory, instead of "2 * application_size", but it's not "background" or "autonomous" - to load the new version of the application, you have to stop the old version and explicitly run the bootloader somehow... Usually the bootloader is protected an cannot replace itself (nor be replaced by the application.)
You can get ... complicated.Certain internet routers, back in the days before cheap flash, would normally copy (uncompress, actually) a complete ROM image into RAM, occupying ~70% of RAM. But sometimes you'd want to download a newer image to run, using one of the many supported network interfaces. So the main image would download an "incomplete" "secondary bootstrap" that only used 20% of RAM (by leaving out big features irrelevant to downloading, like non-IP prototocols), and then run the secondary bootstrap to download the image that you actually wanted to run. Fun Times!